     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.1.3
     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: 02/06/2022 (v0.2.1.3) ]
    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                                  ;
    24                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    25                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    26                                  ; <Bell Laboratories (17/3/1972)>
    27                                  ; <Preliminary Release of UNIX Implementation Document>
    28                                  ;
    29                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    30                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    31                                  ;
    32                                  ; ****************************************************************************
    33                                  ; 31/12/2021 - 15/05/2022
    34                                  ; nasm unix386.s -l unix386.txt -o unix386 -Z error.txt
    35                                  ; ('unixcopy' utility is used for updating retro unix kernel on runix fs disk)
    36                                  
    37                                  ; 02/01/2022 - Code Optimization
    38                                  ; Runix Kernel v0.2.1.2
    39                                  ; 24/12/2021 - BugFix and Code Optimization
    40                                  ; Runix Kernel v0.2.1.1 
    41                                  
    42                                  ; 24/12/2013
    43                                  
    44                                  ; Entering protected mode:
    45                                  ; Derived from 'simple_asm.txt' source code file and 
    46                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    47                                  ; (gregor.brunmar@home.se)
    48                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    49                                  ;
    50                                  
    51                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    52                                  ; by Michael Chourdakis (2009) 
    53                                  ; http://www.codeproject.com/Articles/45788/
    54                                  ; http://www.michaelchourdakis.com
    55                                  ;
    56                                  
    57                                  ; Global Descriptor Table:
    58                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    59                                  ; by Linus Torvalds (1991-1992)
    60                                  ;
    61                                  
    62                                  KLOAD	equ 10000h ; Kernel loading address
    63                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h
    64                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    65                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    66                                  ; 19/03/2015
    67                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    68                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    69                                  ; 24/03/2015
    70                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    71                                  ; 19/03/2015
    72                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    73                                  		     ; (at the end of the 1st 4MB)
    74                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    75                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    76                                  
    77                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
    78                                  ;; 27/12/2013
    79                                  ;KEND	equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    80                                  
    81                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    82                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    83                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    84                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    85                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    86                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    87                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    88                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    89                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    90                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    91                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    92                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    93                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    94                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    95                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    96                                  ;----------------------------------------
    97                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    98                                  ;-----------------------------------------------------------------------------
    99                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
   100                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
   101                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
   102                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
   103                                  
   104                                  ; Memory Allocation Table Address
   105                                  ; 05/11/2014
   106                                  ; 31/10/2014
   107                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
   108                                  					; the 1st 1 MB memory space.
   109                                  					; (This address must be aligned
   110                                  					;  on 128 KB boundary, if it will be
   111                                  					;  changed later.)
   112                                  					; ((lower 17 bits of 32 bit M.A.T.
   113                                  					;   address must be ZERO)).
   114                                  					; ((((Reason: 32 bit allocation 
   115                                  					;     instructions, dword steps)))
   116                                  					; (((byte >> 12 --> page >> 5)))  
   117                                  ;04/11/2014	
   118                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   119                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   120                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   121                                  ;
   122                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   123                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   124                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   125                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   126                                  
   127                                  ; 17/02/2015 (unix386.s)
   128                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   129                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   130                                  ;
   131                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   132                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   133                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   134                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   135                                  
   136                                  
   137                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   138                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   139                                  ;
   140                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   141                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   142                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   143                                  		      ; otherwise it is standard FDPT with physical values 	
   144                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   145                                  		      ; (obsolete for IDE/ATA drives)
   146                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   147                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   148                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   149                                  			; Bit 4 : Reserved. Always 0
   150                                  			; Bit 3 : Set to 1 if more than 8 heads
   151                                  			; Bit 2-0 : Reserved. Alsways 0
   152                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   153                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   154                                  
   155                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   156                                  ; (11 bytes long) will be used by diskette handler/bios
   157                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   158                                  
   159                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   160                                  
   161                                  [ORG 0]
   162                                  
   163                                  KSTART: ; 01/01/2022
   164                                   
   165                                  	; 12/11/2014
   166                                  	; Save boot drive number (that is default root drive)
   167 00000000 8816[7A66]              	mov	[boot_drv], dl ; physical drv number
   168                                  
   169                                  	; Determine installed memory
   170                                  	; 31/10/2014
   171                                  	;
   172 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   173 00000007 CD15                    	int	15h	   ; for large configurations
   174 00000009 7308                    	jnc	short chk_ms
   175 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   176 0000000D CD15                    	int	15h
   177                                  	;	   
   178                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   179                                  	;out	70h, al ; select CMOS register
   180                                  	;in	al, 71h ; read data (1 byte)
   181                                  	;mov	cl, al
   182                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   183                                  	;out	70h, al ; select CMOS register
   184                                  	;in	al, 71h ; read data (1 byte)
   185                                  	;mov	ch, al
   186                                   	;      
   187 0000000F 89C1                    	mov	cx, ax
   188 00000011 31D2                    	xor	dx, dx
   189                                  chk_ms:
   190 00000013 890E[1069]              	mov	[mem_1m_1k], cx
   191 00000017 8916[1469]              	mov	[mem_16m_64k], dx
   192                                  	; 05/11/2014
   193                                  	;and	dx, dx
   194                                  	;jz	short L2
   195 0000001B 81F90004                        cmp     cx, 1024
   196 0000001F 7351                    	jnb	short L0
   197                                  		 ; insufficient memory_error	
   198                                  		 ; Minimum 2 MB memory is needed... 
   199                                  	; 05/11/2014
   200                                  	; (real mode error printing)
   201 00000021 FB                      	sti
   202 00000022 BE[3600]                	mov	si, msg_out_of_memory
   203 00000025 BB0700                  	mov	bx, 7
   204 00000028 B40E                    	mov	ah, 0Eh	; write tty
   205                                  oom_1:
   206 0000002A AC                      	lodsb
   207 0000002B 08C0                    	or	al, al
   208 0000002D 7404                    	jz	short oom_2
   209 0000002F CD10                    	int	10h
   210 00000031 EBF7                    	jmp	short oom_1
   211                                  oom_2:
   212 00000033 F4                              hlt
   213 00000034 EBFD                    	jmp	short oom_2
   214                                  
   215                                  ; 02/01/2022
   216                                  ; 05/11/2014
   217                                  msg_out_of_memory:
   218 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   219 00000039 496E73756666696369-             db      'Insufficient memory !'
   219 00000042 656E74206D656D6F72-
   219 0000004B 792021             
   220 0000004E 0D0A                    	db	0Dh, 0Ah
   221                                  _int13h_48h_buffer: ; 02/01/2022 (Runix Kernel v0.2.1.2, 'diskinit.inc')
   222 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   222 00000059 324D42206D656D6F72-
   222 00000062 79206973206E656564-
   222 0000006B 65642E29           
   223 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   224                                  
   225                                  L0:
   226                                  %include 'diskinit.inc' ; 07/03/2015
   227                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - DISKINIT.INC
   228                              <1> ; Last Modification: 09/05/2022
   229                              <1> 
   230                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   231                              <1> 
   232                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   233                              <1> 
   234                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   235                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   236                              <1> ;L0:
   237                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   238                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   239 00000072 BA7F00              <1> 	mov	dx, 7Fh
   240                              <1> L1:	
   241 00000075 FEC2                <1> 	inc	dl
   242 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   243                              <1> 			; Phoenix EDD v1.1 - EDD v3
   244 00000079 BBAA55              <1> 	mov	bx, 55AAh
   245 0000007C CD13                <1> 	int 	13h
   246 0000007E 721A                <1> 	jc	short L2
   247                              <1> 
   248 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   249 00000084 7514                <1> 	jne	short L2
   250 00000086 FE06[7D66]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   251 0000008A 8816[7C66]          <1>         mov     [last_drv], dl  ; last hard disk number
   252 0000008E BB[0066]            <1> 	mov	bx, hd0_type - 80h
   253 00000091 01D3                <1> 	add	bx, dx	 
   254 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   255                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   256                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   257                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   258                              <1>                          ;            (EDD) ready (DPTE ready)
   259                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   260                              <1>                          ;            (EDD-3)
   261                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   262 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   263 00000098 72DB                <1> 	jb	short L1
   264                              <1> L2:
   265                              <1> 	; 23/11/2014
   266                              <1> 	; 19/11/2014
   267 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   268                              <1> 	; 04/02/2016 (esi -> si)
   269 0000009C BE[7E66]            <1> 	mov	si, fd0_type
   270                              <1> L3:
   271                              <1> 	; 14/01/2015
   272 0000009F 8816[7B66]          <1> 	mov	[drv], dl
   273                              <1> 	;
   274 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   275 000000A5 CD13                <1> 	int	13h	
   276 000000A7 7210                <1> 	jc	short L4
   277                              <1> 		; BL = drive type (for floppy drives)
   278                              <1> 		; DL = number of floppy drives
   279                              <1> 		;		
   280                              <1> 		; ES:DI = Address of DPT from BIOS
   281                              <1> 		;
   282 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   283                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   284                              <1> 	; 14/01/2015
   285 000000AB E8BB01              <1> 	call	set_disk_parms
   286                              <1> 	; 10/12/2014
   287 000000AE 81FE[7E66]          <1> 	cmp	si, fd0_type
   288 000000B2 7705                <1> 	ja	short L4
   289 000000B4 46                  <1> 	inc	si ; fd1_type
   290 000000B5 B201                <1> 	mov	dl, 1
   291 000000B7 EBE6                <1> 	jmp	short L3
   292                              <1> L4:
   293                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   294 000000B9 B27F                <1> 	mov	dl, 7Fh
   295                              <1> 	; 24/12/2014 (Temporary)
   296 000000BB 803E[7D66]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   297                              <1> 	;ja	L10       ; yes, all fixed disk operations
   298                              <1> 			  ; will be performed according to
   299                              <1> 			  ; present EDD specification
   300                              <1> 	; 02/01/2022
   301 000000C0 7603                <1> 	jna	short L5
   302 000000C2 E99100              <1> 	jmp	L10
   303                              <1> L5:
   304 000000C5 FEC2                <1> 	inc 	dl
   305 000000C7 8816[7B66]          <1>         mov     [drv], dl
   306 000000CB 8816[7C66]          <1>         mov     [last_drv], dl ; 14/01/2015
   307 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   308 000000D1 CD13                <1> 	int	13h	; (conventional function)
   309                              <1> 	;jc	L13	; fixed disk drive not ready
   310                              <1> 	; 02/01/2022
   311 000000D3 7303                <1> 	jnc	short L6
   312 000000D5 E98301              <1> 	jmp	L13
   313                              <1> L6:
   314 000000D8 8816[7D66]          <1>         mov     [hdc], dl ; number of drives
   315                              <1> 	;; 14/01/2013
   316                              <1> 	;;push	cx
   317 000000DC E88A01              <1> 	call	set_disk_parms
   318                              <1> 	;;pop	cx
   319                              <1> 	;
   320                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   321 000000DF 8A16[7B66]          <1>         mov     dl, [drv]
   322 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   323 000000E6 80FA80              <1> 	cmp	dl, 80h
   324 000000E9 7603                <1> 	jna	short L7
   325 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   326                              <1> L7:	
   327 000000EE 31C0                <1> 	xor	ax, ax
   328 000000F0 8ED8                <1> 	mov	ds, ax
   329 000000F2 8B37                <1>         mov     si, [bx]
   330 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   331 000000F7 8ED8                <1> 	mov	ds, ax
   332 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   333                              <1> 	;jne	L12 ; invalid FDPT
   334                              <1> 	; 02/01/2022
   335 000000FC 7403                <1> 	je	short L7_8
   336 000000FE E95601              <1> 	jmp	L12
   337                              <1> L7_8:
   338 00000101 BF0000              <1> 	mov	di, HD0_DPT
   339 00000104 80FA80              <1> 	cmp	dl, 80h
   340 00000107 7603                <1> 	jna	short L8
   341 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   342                              <1> L8:
   343                              <1> 	; 30/12/2014
   344 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   345 0000010F 8EC0                <1> 	mov	es, ax
   346                              <1> 	; 24/12/2014
   347 00000111 B90800              <1> 	mov	cx, 8
   348 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   349 00000116 8CC8                <1> 	mov	ax, cs
   350 00000118 8ED8                <1> 	mov	ds, ax
   351                              <1> 	; 02/02/2015
   352 0000011A 8A0E[7B66]          <1>         mov     cl, [drv]
   353 0000011E 88CB                <1> 	mov	bl, cl
   354 00000120 B8F001              <1> 	mov	ax, 1F0h
   355 00000123 80E301              <1> 	and	bl, 1
   356 00000126 7406                <1> 	jz	short L9
   357 00000128 C0E304              <1> 	shl	bl, 4
   358 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   359                              <1> L9:
   360 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   361 0000012F 050602              <1> 	add	ax, 206h
   362 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   363 00000133 88D8                <1> 	mov	al, bl
   364 00000135 04A0                <1> 	add	al, 0A0h
   365 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   366                              <1> 	;
   367 00000138 FE06[7B66]          <1> 	inc	byte [drv]
   368 0000013C BB[0066]            <1> 	mov	bx, hd0_type - 80h
   369 0000013F 01CB                <1> 	add	bx, cx
   370 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   371 00000144 A0[7D66]            <1> 	mov	al, [hdc]
   372 00000147 FEC8                <1> 	dec	al
   373                              <1> 	;jz	L13
   374                              <1> 	; 02/01/2022
   375 00000149 7408                <1> 	jz	short L9_10
   376 0000014B 80FA80              <1> 	cmp	dl, 80h
   377                              <1>         ;jna	L5
   378                              <1> 	;jmp	L13
   379                              <1> 	; 02/01/2022
   380 0000014E 7703                <1> 	ja	short L9_10
   381 00000150 E972FF              <1> 	jmp	L5
   382                              <1> L9_10:
   383 00000153 E90501              <1>         jmp     L13
   384                              <1> L10:
   385 00000156 FEC2                <1> 	inc 	dl
   386                              <1> 	; 25/12/2014
   387 00000158 8816[7B66]          <1> 	mov	[drv], dl
   388 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   389 0000015E CD13                <1> 	int	13h	; (conventional function)
   390                              <1> 	;jc	L13
   391                              <1> 	; 02/01/2022
   392 00000160 72F1                <1> 	jc	short L9_10
   393                              <1> 	; 14/01/2015
   394 00000162 8A16[7B66]          <1> 	mov	dl, [drv]
   395 00000166 52                  <1> 	push	dx
   396 00000167 51                  <1> 	push	cx
   397 00000168 E8FE00              <1> 	call	set_disk_parms
   398 0000016B 59                  <1> 	pop	cx
   399 0000016C 5A                  <1> 	pop	dx
   400                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   401                              <1> 	; 04/02/2016 (esi -> si)
   402                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   403                              <1> 	;		 ; at the '_end' of kernel.
   404                              <1> 	;mov	word [si], 30
   405                              <1> 	; 06/07/2016
   406 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   407                              <1> 	; 09/07/2016
   408 00000170 B81E00              <1> 	mov	ax, 001Eh
   409 00000173 8824                <1> 	mov	[si], ah ; 0
   410 00000175 46                  <1> 	inc	si
   411 00000176 8904                <1> 	mov	word [si], ax
   412                              <1>  	; word [si] = 30
   413                              <1> 	;
   414 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   415 0000017A CD13                <1> 	int	13h
   416                              <1>         ;jc	L13
   417                              <1> 	; 02/01/2022
   418 0000017C 72D5                <1> 	jc	short L9_10
   419                              <1> 	; 04/02/2016 (ebx -> bx)
   420                              <1> 	; 14/01/2015
   421                              <1> 	;sub	bx, bx
   422 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   423 00000180 88D3                <1> 	mov	bl, dl
   424 00000182 80EB80              <1> 	sub	bl, 80h
   425 00000185 81C3[8066]          <1> 	add	bx, hd0_type
   426 00000189 8A07                <1> 	mov 	al, [bx]
   427 0000018B 0C80                <1> 	or	al, 80h
   428 0000018D 8807                <1> 	mov 	[bx], al	
   429 0000018F 81EB[7E66]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   430 00000193 81C3[CA66]          <1> 	add	bx, drv.status
   431 00000197 8807                <1> 	mov	[bx], al
   432                              <1> 	; 04/02/2016 (eax -> ax)
   433 00000199 8B4410              <1> 	mov	ax, [si+16]
   434 0000019C 854412              <1> 	test	ax, [si+18]
   435 0000019F 7413                <1> 	jz	short L10_A0h 
   436                              <1> 			; 'CHS only' disks on EDD system 
   437                              <1> 			;  are reported with ZERO disk size
   438 000001A1 81EB[CA66]          <1> 	sub	bx, drv.status
   439 000001A5 C1E302              <1> 	shl	bx, 2
   440 000001A8 81C3[AE66]          <1> 	add	bx, drv.size ; disk size (in sectors)
   441 000001AC 8907                <1> 	mov	[bx], ax
   442 000001AE 8B4412              <1> 	mov	ax, [si+18]
   443                              <1> 	;mov	[bx], ax
   444                              <1> 	; 02/01/2022 (BugFix)
   445 000001B1 894702              <1> 	mov	[bx+2], ax
   446                              <1> 
   447                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   448                              <1> 	 ; for CHS disks (28/02/2015)
   449                              <1> 	; 30/12/2014
   450 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   451 000001B7 88D0                <1> 	mov	al, dl
   452 000001B9 83E003              <1> 	and 	ax, 3
   453 000001BC C0E005              <1> 	shl	al, 5 ; *32
   454 000001BF 01C7                <1> 	add 	di, ax
   455 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   456 000001C4 8EC0                <1> 	mov	es, ax
   457                              <1> 	;
   458 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   459 000001C8 88CC                <1> 	mov	ah, cl	
   460 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   461 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   462 000001CE AB                  <1> 	stosw		
   463 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   464 000001D1 FEC0                <1> 	inc	al
   465 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   466 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   467 000001D6 AA                  <1> 	stosb
   468 000001D7 8A440C              <1> 	mov	al, [si+12]
   469 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   470 000001DB 31C0                <1>  	xor	ax, ax
   471                              <1> 	;dec	ax	 ; 02/01/2015 
   472 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   473                              <1> 	;xor	al, al	 ; 02/01/2015	
   474 000001DE AA                  <1> 	stosb		 ; reserved
   475 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   476                              <1> 		         ; (do not disable retries, 
   477                              <1> 			 ; more than 8 heads)
   478 000001E1 AA                  <1> 	stosb
   479 000001E2 8B4404              <1> 	mov	ax, [si+4]
   480 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   481                              <1> 	;push	ax	 ; 02/01/2015
   482 000001E6 8A4408              <1> 	mov	al, [si+8]
   483 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   484 000001EA 29C0                <1> 	sub 	ax, ax
   485                              <1> 	;pop	ax	 ; 02/01/2015	
   486 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   487 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   488 000001EF 243F                <1> 	and 	al, 3Fh	
   489 000001F1 AA                  <1> 	stosb
   490                              <1> 	;sub	al, al	 ; checksum
   491                              <1> 	;stosb
   492                              <1> 	;
   493 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   494 000001F5 AD                  <1> 	lodsw
   495 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   496 000001F7 AD                  <1> 	lodsw
   497 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   498                              <1> 	;
   499                              <1> 	; checksum calculation
   500 000001F9 89FE                <1> 	mov	si, di
   501 000001FB 06                  <1> 	push	es
   502 000001FC 1F                  <1> 	pop	ds
   503                              <1> 	;mov	cx, 16
   504 000001FD B90F00              <1> 	mov 	cx, 15
   505 00000200 29CE                <1> 	sub	si, cx
   506 00000202 30E4                <1> 	xor	ah, ah
   507                              <1> 	;del	cl
   508                              <1> L11:		
   509 00000204 AC                  <1> 	lodsb
   510 00000205 00C4                <1> 	add	ah, al
   511 00000207 E2FB                <1> 	loop	L11
   512                              <1> 	;
   513 00000209 88E0                <1> 	mov	al, ah
   514 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   515 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   516                              <1> 	;
   517 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   518 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   519                              <1> 	;
   520                              <1> 	; 23/02/2015
   521 00000210 57                  <1> 	push	di
   522                              <1> 	; ES:DI points to DPTE (FDPTE) location
   523                              <1> 	;mov	cx, 8
   524 00000211 B108                <1> 	mov	cl, 8
   525 00000213 F3A5                <1> 	rep	movsw	
   526                              <1> 	;
   527                              <1> 	; 23/02/2015
   528                              <1> 	; (P)ATA drive and LBA validation
   529                              <1> 	; (invalidating SATA drives and setting
   530                              <1> 	; CHS type I/O for old type fixed disks)
   531 00000215 5B                  <1> 	pop	bx
   532 00000216 8CC8                <1> 	mov	ax, cs
   533 00000218 8ED8                <1> 	mov	ds, ax
   534 0000021A 268B07              <1> 	mov	ax, [es:bx]
   535 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   536 00000220 7418                <1> 	je	short L11a
   537 00000222 3D7001              <1> 	cmp	ax, 170h
   538 00000225 7413                <1> 	je	short L11a
   539                              <1> 	; invalidation 
   540                              <1> 	; (because base port address is not 1F0h or 170h)
   541 00000227 30FF                <1> 	xor	bh, bh
   542 00000229 88D3                <1> 	mov	bl, dl
   543 0000022B 80EB80              <1> 	sub	bl, 80h
   544 0000022E C687[8066]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   545 00000233 808F[CC66]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   546 00000238 EB14                <1> 	jmp	short L11b
   547                              <1> L11a:	
   548                              <1> 	; LBA validation
   549 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   550 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   551 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   552                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   553 00000242 28FF                <1> 	sub	bh, bh
   554 00000244 88D3                <1> 	mov	bl, dl
   555 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   556 00000249 80A7[CC66]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   557                              <1> 				; bit 0 = LBA ready bit
   558                              <1> 	; 'diskio' procedure will check this bit !
   559                              <1> L11b:
   560 0000024E 3A16[7C66]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   561 00000252 7307                <1>         jnb     short L13
   562 00000254 E9FFFE              <1>         jmp     L10
   563                              <1> L12:
   564                              <1> 	; Restore data registers
   565 00000257 8CC8                <1> 	mov	ax, cs
   566 00000259 8ED8                <1> 	mov	ds, ax	
   567                              <1> L13:
   568                              <1> 	; 13/12/2014
   569 0000025B 0E                  <1> 	push	cs
   570 0000025C 07                  <1> 	pop	es
   571                              <1> L14:
   572 0000025D B411                <1> 	mov 	ah, 11h
   573 0000025F CD16                <1> 	int 	16h
   574                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   575                              <1> 	; 02/01/2022
   576 00000261 7465                <1> 	jz	short L16
   577 00000263 B010                <1> 	mov	al, 10h
   578 00000265 CD16                <1> 	int 	16h
   579 00000267 EBF4                <1> 	jmp 	short L14
   580                              <1> L15:
   581                              <1> 
   582                              <1> ; //////
   583                              <1> 
   584                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   585                              <1> %if 0
   586                              <1> 	; 24/11/2014
   587                              <1> 	; 19/11/2014
   588                              <1> 	; 14/11/2014
   589                              <1> 	; Temporary code for disk searching code check
   590                              <1> 	;
   591                              <1> 	; This code will show existing (usable) drives and also
   592                              <1> 	; will show EDD interface support status for hard disks		
   593                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   594                              <1> 	; no need to get it again in protected mode...) 
   595                              <1> 	;	
   596                              <1> 	; 13/11/2014
   597                              <1> 	mov	bx, 7
   598                              <1> 	mov	ah, 0Eh
   599                              <1> 	mov	al, [fd0_type]
   600                              <1> 	and	al, al
   601                              <1> 	jz	short L15a
   602                              <1> 	mov	dl, al
   603                              <1> 	mov	al, 'F'
   604                              <1> 	int 	10h
   605                              <1> 	mov	al, 'D'
   606                              <1> 	int 	10h
   607                              <1> 	mov	al, '0'
   608                              <1> 	int 	10h
   609                              <1> 	mov	al, ' '
   610                              <1> 	int	10h
   611                              <1> 	call	L15c
   612                              <1> 	mov	al, ' '
   613                              <1> 	int	10h
   614                              <1> 	;
   615                              <1> 	mov	al, [fd1_type]
   616                              <1> 	and	al, al
   617                              <1> 	jz	short L15a
   618                              <1> 	mov	dl, al
   619                              <1> 	mov	al, 'F'
   620                              <1> 	int 	10h
   621                              <1> 	mov	al, 'D'
   622                              <1> 	int 	10h
   623                              <1> 	mov	al, '1'
   624                              <1> 	int 	10h
   625                              <1> 	mov	al, ' '
   626                              <1> 	int	10h
   627                              <1> 	call	L15c
   628                              <1> 	mov	al, ' '
   629                              <1> 	int	10h
   630                              <1> 	mov	al, ' '
   631                              <1> 	int	10h
   632                              <1> L15a:
   633                              <1> 	mov	al, [hd0_type]
   634                              <1> 	and	al, al
   635                              <1> 	jz	short L15b
   636                              <1> 	mov	dl, al
   637                              <1> 	mov	al, 'H'
   638                              <1> 	int 	10h
   639                              <1> 	mov	al, 'D'
   640                              <1> 	int 	10h
   641                              <1> 	mov	al, '0'
   642                              <1> 	int 	10h
   643                              <1> 	mov	al, ' '
   644                              <1> 	int 	10h
   645                              <1> 	call	L15c
   646                              <1> 	mov	al, ' '
   647                              <1> 	int	10h
   648                              <1> 	;
   649                              <1> 	mov	al, [hd1_type]
   650                              <1> 	and	al, al
   651                              <1> 	jz	short L15b
   652                              <1> 	mov	dl, al
   653                              <1> 	mov	al, 'H'
   654                              <1> 	int 	10h
   655                              <1> 	mov	al, 'D'
   656                              <1> 	int 	10h
   657                              <1> 	mov	al, '1'
   658                              <1> 	int 	10h
   659                              <1> 	mov	al, ' '
   660                              <1> 	int 	10h
   661                              <1> 	call	L15c
   662                              <1> 	mov	al, ' '
   663                              <1> 	int	10h
   664                              <1> 	;
   665                              <1> 	mov	al, [hd2_type]
   666                              <1> 	and	al, al
   667                              <1> 	jz	short L15b
   668                              <1> 	mov	dl, al
   669                              <1> 	mov	al, 'H'
   670                              <1> 	int 	10h
   671                              <1> 	mov	al, 'D'
   672                              <1> 	int 	10h
   673                              <1> 	mov	al, '2'
   674                              <1> 	int 	10h
   675                              <1> 	mov	al, ' '
   676                              <1> 	int 	10h
   677                              <1> 	call	L15c
   678                              <1> 	mov	al, ' '
   679                              <1> 	int	10h
   680                              <1> 	;
   681                              <1> 	mov	al, [hd3_type]
   682                              <1> 	and	al, al
   683                              <1> 	jz	short L15b
   684                              <1> 	mov	dl, al
   685                              <1> 	mov	al, 'H'
   686                              <1> 	int 	10h
   687                              <1> 	mov	al, 'D'
   688                              <1> 	int 	10h
   689                              <1> 	mov	al, '3'
   690                              <1> 	int 	10h
   691                              <1> 	mov	al, ' '
   692                              <1> 	int 	10h
   693                              <1> 	call	L15c
   694                              <1> 	mov	al, ' '
   695                              <1> 	int	10h
   696                              <1> 	;
   697                              <1> L15b:
   698                              <1> 	mov	al, 0Dh
   699                              <1> 	int 	10h	
   700                              <1> 	mov	al, 0Ah
   701                              <1> 	int 	10h
   702                              <1> 	;;xor	ah, ah
   703                              <1> 	;;int 	16h	
   704                              <1> 	;
   705                              <1>         ;jmp	L16  ; jmp short L16
   706                              <1>         ; 02/01/2022
   707                              <1> 	jmp	short L16
   708                              <1> 	;
   709                              <1> L15c:
   710                              <1> 	mov	dh, dl
   711                              <1> 	shr	dh, 4
   712                              <1> 	add	dh, 30h
   713                              <1> 	and	dl, 15
   714                              <1> 	add	dl, 30h
   715                              <1> 	mov	al, dh
   716                              <1> 	int	10h
   717                              <1> 	mov	al, dl
   718                              <1> 	int	10h
   719                              <1> 	retn
   720                              <1> 	;
   721                              <1> 	; end of temporary code for disk searching code check
   722                              <1> 
   723                              <1> %endif
   724                              <1> 
   725                              <1> ; //////
   726                              <1> 
   727                              <1> set_disk_parms:
   728                              <1> 	; 09/05/2022
   729                              <1> 	;	disksize = cylinders*spt*heads (*)
   730                              <1> 	; (fd0&fd1 drv.size is calculated with total cylinders) 
   731                              <1> 	;
   732                              <1> 	; 04/02/2016 (ebx -> bx)
   733                              <1> 	; 10/07/2015
   734                              <1> 	; 14/01/2015
   735                              <1> 	;push	bx
   736 00000269 28FF                <1> 	sub	bh, bh
   737 0000026B 8A1E[7B66]          <1> 	mov	bl, [drv]
   738 0000026F 80FB80              <1> 	cmp	bl, 80h
   739 00000272 7203                <1> 	jb	short sdp0
   740 00000274 80EB7E              <1> 	sub	bl, 7Eh
   741                              <1> sdp0:	
   742 00000277 81C3[CA66]          <1> 	add	bx, drv.status
   743 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   744                              <1> 	;
   745 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   746 00000280 88CC                <1> 	mov	ah, cl ; 
   747 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   748 00000285 81EB[CA66]          <1> 	sub	bx, drv.status
   749 00000289 D0E3                <1> 	shl	bl, 1
   750 0000028B 81C3[8466]          <1> 	add	bx, drv.cylinders
   751 0000028F 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   752 00000290 8907                <1> 	mov	[bx], ax
   753 00000292 50                  <1> 	push	ax ; ** cylinders
   754 00000293 81EB[8466]          <1> 	sub	bx, drv.cylinders
   755 00000297 81C3[9266]          <1> 	add	bx, drv.heads
   756 0000029B 30E4                <1> 	xor	ah, ah
   757 0000029D 88F0                <1> 	mov	al, dh ; heads
   758 0000029F 40                  <1> 	inc	ax
   759 000002A0 8907                <1> 	mov	[bx], ax
   760 000002A2 81EB[9266]          <1>         sub     bx, drv.heads
   761 000002A6 81C3[A066]          <1>         add     bx, drv.spt
   762 000002AA 30ED                <1> 	xor	ch, ch
   763 000002AC 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   764 000002AF 890F                <1> 	mov	[bx], cx
   765 000002B1 81EB[A066]          <1>         sub     bx, drv.spt
   766 000002B5 D1E3                <1> 	shl	bx, 1
   767 000002B7 81C3[AE66]          <1> 	add	bx, drv.size ; disk size (in sectors)
   768                              <1> 	; LBA size = cylinders * heads * secpertrack
   769 000002BB F7E1                <1> 	mul	cx 
   770 000002BD 89C2                <1> 	mov	dx, ax	; heads*spt					
   771 000002BF 58                  <1> 	pop	ax ; ** cylinders
   772                              <1> 	; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads)
   773                              <1> 	;dec	ax ; 1 cylinder reserved (!?) ; (*)
   774 000002C0 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   775 000002C2 8907                <1> 	mov	[bx], ax
   776 000002C4 895702              <1> 	mov	[bx+2], dx
   777                              <1> 	;
   778                              <1> 	;pop	bx
   779 000002C7 C3                  <1> 	retn
   780                              <1> 
   781                              <1> ;align 2
   782                              <1> 
   783                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   784                              <1> ;heads     :  dw 0, 0, 0, 0, 0, 0
   785                              <1> ;spt       :  dw 0, 0, 0, 0, 0, 0
   786                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   787                              <1> 
   788                              <1> ;last_drv:
   789                              <1> ;	db  0
   790                              <1> ;drv_status:
   791                              <1> ;	db  0,0,0,0,0,0
   792                              <1> ;	db 0
   793                              <1> 
   794                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   795                              <1> 
   796                              <1> L16:
   227                                  
   228                                  	; 10/11/2014
   229 000002C8 FA                           	cli	; Disable interrupts (clear interrupt flag)
   230                                  		; Reset Interrupt MASK Registers (Master&Slave)
   231                                  	;mov	al, 0FFh	; mask off all interrupts
   232                                  	;out	21h, al		; on master PIC (8259)
   233                                  	;jmp 	$+2  ; (delay)
   234                                  	;out	0A1h, al	; on slave PIC (8259)
   235                                  	;
   236                                  	; Disable NMI 
   237 000002C9 B080                    	mov   	al, 80h 
   238 000002CB E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   239                                  	;23/02/2015
   240 000002CD 90                      	nop			;
   241                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   242                                  				; for preventing unknown state (!?)
   243                                  
   244                                  	; 02/01/2022
   245                                  	%define KERNELFSIZE KEND-KSTART 
   246                                  	;
   247                                   	; 20/08/2014
   248                                  	; Moving the kernel 64 KB back (to physical address 0)
   249                                  	; DS = CS = 1000h
   250                                  	; 05/11/2014
   251 000002CE 31C0                    	xor	ax, ax
   252 000002D0 8EC0                    	mov	es, ax ; ES = 0
   253                                  	;
   254                                  	;;mov	cx, (KEND - KLOAD)/4
   255                                  	;mov	cx, (KERNELFSIZE+3)/4 ; 02/01/2022
   256 000002D2 B98C34                  	mov	cx, (KERNELFSIZE+1)/2 ; 02/01/2022
   257 000002D5 31F6                    	xor	si, si
   258 000002D7 31FF                    	xor	di, di
   259                                  	;rep	movsd
   260 000002D9 F3A5                    	rep	movsw ; 02/01/2022
   261                                  	;
   262 000002DB 06                      	push	es ; 0
   263 000002DC 68[E002]                	push	L17
   264 000002DF CB                      	retf
   265                                  	;
   266                                  L17:
   267                                  	; Turn off the floppy drive motor
   268 000002E0 BAF203                          mov     dx, 3F2h
   269 000002E3 EE                              out     dx, al ; 0 ; 31/12/2013
   270                                  
   271                                  	; Enable access to memory above one megabyte
   272                                  L18:
   273 000002E4 E464                    	in	al, 64h
   274 000002E6 A802                    	test	al, 2
   275 000002E8 75FA                            jnz     short L18
   276 000002EA B0D1                    	mov	al, 0D1h	; Write output port
   277 000002EC E664                    	out	64h, al
   278                                  L19:
   279 000002EE E464                    	in	al, 64h
   280 000002F0 A802                    	test	al, 2
   281 000002F2 75FA                            jnz     short L19
   282 000002F4 B0DF                    	mov	al, 0DFh	; Enable A20 line
   283 000002F6 E660                    	out	60h, al
   284                                  ;L20:
   285                                  	;
   286                                  	; Load global descriptor table register
   287                                  
   288                                          ;mov     ax, cs
   289                                          ;mov     ds, ax
   290                                  
   291 000002F8 2E0F0116[A063]                  lgdt    [cs:gdtd]
   292                                  
   293 000002FE 0F20C0                          mov     eax, cr0
   294                                  	; or 	eax, 1
   295 00000301 40                      	inc     ax
   296 00000302 0F22C0                  	mov     cr0, eax
   297                                  
   298                                  	; Jump to 32 bit code
   299                                  	
   300 00000305 66                      	db 66h 			; Prefix for 32-bit
   301 00000306 EA                      	db 0EAh 		; Opcode for far jump
   302 00000307 [0D030000]              	dd StartPM 		; Offset to start, 32-bit
   303                                  				; (1000h:StartPM = StartPM + 10000h)
   304 0000030B 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   305                                  				; assuming that StartPM resides in code32
   306                                  
   307                                  [BITS 32] 
   308                                  
   309                                  StartPM:
   310                                  	; Kernel Base Address = 0 ; 30/12/2013
   311 0000030D 66B81000                	mov ax, KDATA           ; Save data segment identifier
   312 00000311 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   313 00000313 8EC0                           	mov es, ax              ; Move data segment into ES register
   314 00000315 8EE0                           	mov fs, ax              ; Move data segment into FS register
   315 00000317 8EE8                          	mov gs, ax              ; Move data segment into GS register
   316 00000319 8ED0                            mov ss, ax              ; Move data segment into SS register
   317 0000031B BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   318                                  
   319                                  clear_bss: ; Clear uninitialized data area
   320                                  	; 11/03/2015
   321 00000320 31C0                    	xor	eax, eax ; 0
   322                                  	;mov	ecx, (bss_end - bss_start)/4
   323                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   324                                  	; 02/01/2022
   325 00000322 B9BD050000              	mov	ecx, BSS_SIZE/4
   326 00000327 BF[20690000]            	mov	edi, bss_start
   327 0000032C F3AB                    	rep	stosd  		
   328                                  
   329                                  memory_init:
   330                                  	; Initialize memory allocation table and page tables
   331                                  	;
   332                                  	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   333                                  	; 16/11/2014
   334                                  	; 15/11/2014
   335                                  	; 07/11/2014
   336                                  	; 06/11/2014
   337                                  	; 05/11/2014
   338                                  	; 04/11/2014
   339                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   340                                  	;
   341                                  ;	xor	eax, eax
   342                                  ;	xor 	ecx, ecx
   343 0000032E B108                    	mov	cl, 8
   344 00000330 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   345 00000335 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   346                                  				   ; for the first 1 MB memory
   347                                  	;
   348 00000337 8B0D[10690000]          	mov	ecx, [mem_1m_1k]   ; 02/01/2022	
   349                                  	;mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   350                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   351                                  	;shr	cx, 2		   ; convert 1 KB count to 4 KB count
   352 0000033D C1E902                  	shr	ecx, 2	; 02/01/2022
   353 00000340 890D[906B0000]          	mov	[free_pages], ecx
   354 00000346 8B15[14690000]          	mov	edx, [mem_16m_64k] ; 02/01/2022
   355                                  	;mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   356                                  				   ; between 16 MB and 4 GB.
   357                                  	;or	dx, dx
   358 0000034C 09D2                    	or	edx, edx ; 02/01/2022
   359 0000034E 7412                    	jz	short mi_0
   360                                  	;
   361                                  	;mov	ax, dx
   362 00000350 89D0                    	mov	eax, edx ; 02/01/2022
   363 00000352 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   364 00000355 0105[906B0000]          	add	[free_pages], eax
   365 0000035B 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   366 00000360 EB06                    	jmp	short mi_1
   367                                  mi_0:
   368                                  	;mov	ax, cx
   369 00000362 89C8                    	mov	eax, ecx ; 02/01/2022	 
   370 00000364 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB
   371                                  mi_1:
   372 00000368 A3[8C6B0000]            	mov	[memory_size], eax ; Total available memory in pages
   373                                  				   ; 1 alloc. tbl. bit = 1 memory page
   374                                  				   ; 32 allocation bits = 32 mem. pages
   375                                  	;
   376 0000036D 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page
   377 00000372 C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   378                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   379                                  				   ;  --> x M.A.T. pages, if y = 0
   380                                  	;mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages
   381 00000375 A3[A06B0000]            	mov	[mat_size], eax ; 02/01/2022
   382 0000037A C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   383                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   384 0000037D 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   385                                  	; Set/Calculate Kernel's Page Directory Address
   386 0000037F 81C300001000            	add	ebx, MEM_ALLOC_TBL
   387 00000385 891D[886B0000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   388                                  				   ; just after the last M.A.T. page
   389                                  	;
   390 0000038B 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   391 0000038E A3[986B0000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   392                                  	;			   ; (allocation status search must be
   393                                  				   ; stopped after here)
   394 00000393 31C0                    	xor	eax, eax
   395 00000395 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)
   396                                  	;push	cx
   397 00000396 51                      	push	ecx ; 02/01/2022 
   398 00000397 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to
   399                                  				   ; count of 32 allocation bits
   400 0000039A F3AB                    	rep	stosd
   401                                  	;pop	cx
   402 0000039C 59                      	pop	ecx ; 02/01/2022
   403 0000039D 40                      	inc	eax		   ; 0
   404 0000039E 80E11F                  	and	cl, 31		   ; remain bits
   405 000003A1 7412                    	jz	short mi_4
   406 000003A3 8907                    	mov	[edi], eax	   ; reset
   407                                  mi_2:
   408 000003A5 0FAB07                  	bts	[edi], eax	   ; 06/11/2014
   409 000003A8 FEC9                    	dec	cl
   410 000003AA 7404                    	jz	short mi_3
   411 000003AC FEC0                    	inc	al
   412 000003AE EBF5                    	jmp	short mi_2
   413                                  mi_3:
   414 000003B0 28C0                    	sub	al, al	   	   ; 0
   415 000003B2 83C704                  	add	edi, 4		   ; 15/11/2014
   416                                  mi_4:
   417 000003B5 09D2                    	or	edx, edx ; 02/01/2022
   418                                  	;or	dx, dx		  ; check 16M to 4G memory space
   419 000003B7 741F                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   420                                  	;	
   421 000003B9 B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   422                                  	;	
   423 000003BE 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   424 000003C0 7405                    	jz	short mi_5	  ; jump if EDI points to 
   425                                  				  ;         end of first 16 MB	
   426                                  	;shr	ecx, 1		  ; convert to dword count
   427                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   428 000003C2 C1E902                  	shr	ecx, 2	; 02/01/2022
   429 000003C5 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   430                                  				  ; (memory hole under 16 MB)
   431                                  mi_5:
   432 000003C7 89D1                    	mov	ecx, edx ; 02/01/2022
   433                                  	;mov	cx, dx		  ; count of 64 KB memory blocks
   434 000003C9 D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   435 000003CB 9C                      	pushf			  ; 16/11/2014		
   436 000003CC 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   437 000003CD F3AB                    	rep	stosd
   438 000003CF 40                      	inc	eax		  ; 0
   439 000003D0 9D                      	popf			  ; 16/11/2014
   440 000003D1 7305                    	jnc	short mi_6
   441 000003D3 6648                    	dec	ax		  ; eax = 0000FFFFh
   442 000003D5 AB                      	stosd
   443 000003D6 6640                    	inc	ax		  ; 0		
   444                                  mi_6:
   445 000003D8 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   446 000003DA 7309                    	jnb	short mi_7	  ; end of memory allocation table
   447                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   448 000003DC 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   449 000003DE 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   450                                  	;shr	ecx, 1		  ; to dword count
   451                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   452 000003E0 C1E902                  	shr	ecx, 2 ; 02/01/2022	
   453 000003E3 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   454                                  mi_7:
   455                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   456 000003E5 BA00001000              	mov	edx, MEM_ALLOC_TBL
   457                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   458                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   459 000003EA 8B0D[A06B0000]          	mov	ecx, [mat_size] ; 02/01/2022
   460                                  	;mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   461 000003F0 89D7                    	mov	edi, edx
   462 000003F2 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   463                                  				  ; byte offset in M.A.T.
   464                                  				  ; (1 M.A.T. byte points to 
   465                                  				  ;	      32768 bytes)
   466                                  				  ; Note: MEM_ALLOC_TBL address 
   467                                  				  ; must be aligned on 128 KB 
   468                                  				  ; boundary!
   469 000003F5 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   470                                  	; eax = 0
   471 000003F7 290D[906B0000]          	sub	[free_pages], ecx ; 07/11/2014
   472                                  mi_8:
   473 000003FD 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   474                                  	;dec	bl
   475 00000400 FEC9                    	dec	cl
   476 00000402 7404                    	jz	short mi_9
   477 00000404 FEC0                    	inc	al
   478 00000406 EBF5                    	jmp	short mi_8
   479                                  mi_9:
   480                                  	;
   481                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   482                                  	;		(allocate pages for system page tables)
   483                                  
   484                                  	; edx = MEM_ALLOC_TBL
   485 00000408 8B0D[8C6B0000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   486 0000040E 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)
   487 00000414 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   488                                  				 ; page table count (PDE count)
   489                                  	;
   490 00000417 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   491                                  	;
   492 00000418 41                      	inc	ecx		 ; +1 for kernel page directory	
   493                                  	;
   494 00000419 290D[906B0000]          	sub	[free_pages], ecx ; 07/11/2014
   495                                  	;
   496 0000041F 8B35[886B0000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   497 00000425 C1EE0C                  	shr	esi, 12		 ; convert to page number
   498                                  mi_10:
   499 00000428 89F0                    	mov	eax, esi	 ; allocation bit offset
   500 0000042A 89C3                    	mov	ebx, eax
   501 0000042C C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   502 0000042F 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   503                                  				 ;   to align on dword boundary
   504 00000432 83E01F                  	and	eax, 31		 ; set allocation bit position 
   505                                  				 ;  (bit 0 to bit 31)
   506                                  	;
   507 00000435 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   508                                  	;
   509 00000437 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   510                                  	;
   511 0000043A 46                      	inc	esi		 ; next page table
   512 0000043B E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   513                                  				 ; (ecx = page table count + 1)
   514                                  	;
   515 0000043D 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   516                                  	;
   517                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   518                                  	;
   519                                  	; Initialize Kernel's Page Directory
   520 0000043E 8B3D[886B0000]          	mov	edi, [k_page_dir]
   521 00000444 89F8                    	mov	eax, edi
   522 00000446 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   523                                  		     	      ; supervisor + read&write + present
   524 00000448 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)
   525                                  mi_11:
   526 0000044A 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   527                                  			        ; EAX points to next page table
   528 0000044F AB                      	stosd
   529 00000450 E2F8                    	loop	mi_11
   530 00000452 29C0                    	sub	eax, eax	; Empty PDE
   531                                  	;mov	cx, 1024	; Entry count (PGSZ/4)
   532                                  	; 02/01/2022
   533 00000454 B504                    	mov	ch, 4 ; cx = 4*256 = 1024
   534 00000456 29D1                    	sub	ecx, edx
   535 00000458 7402                    	jz	short mi_12
   536 0000045A F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   537                                  	;
   538                                  	; Initialization of Kernel's Page Directory is OK, here.
   539                                  mi_12:
   540                                  	; Initialize Kernel's Page Tables
   541                                  	;
   542                                  	; (EDI points to address of page table 0)
   543                                  	; eax = 0
   544 0000045C 8B0D[8C6B0000]          	mov	ecx, [memory_size] ; memory size in pages
   545 00000462 89CA                    	mov	edx, ecx	; (***)
   546 00000464 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   547                                  			     ; supervisor + read&write + present
   548                                  mi_13:
   549 00000466 AB                      	stosd
   550 00000467 0500100000              	add	eax, 4096	
   551 0000046C E2F8                    	loop	mi_13
   552                                  	; 02/01/2022
   553 0000046E 66B9FF03                	mov	cx, 1023
   554 00000472 21CA                    	and	edx, ecx
   555                                  	;and	dx, 1023	; (***)
   556 00000474 7407                    	jz	short mi_14
   557                                  	;mov	cx, 1024	
   558                                  	; 02/01/2022
   559                                  	;mov	ch, 4 ; cx = 4*256 = 1024
   560 00000476 41                      	inc	ecx ; ecx = 1024
   561 00000477 29D1                    	sub	ecx, edx
   562                                  	;sub	cx, dx		; from dx (<= 1023) to 1024
   563 00000479 31C0                    	xor	eax, eax
   564 0000047B F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   565                                  				; of the last page table
   566                                  mi_14:
   567                                  	;  Initialization of Kernel's Page Tables is OK, here.
   568                                  	;
   569 0000047D 89F8                    	mov	eax, edi	; end of the last page table page
   570                                  			        ; (beginging of user space pages)
   571 0000047F C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   572 00000482 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   573                                  				; aligning on dword boundary
   574                                  	 
   575 00000484 A3[9C6B0000]            	mov	[first_page], eax
   576 00000489 A3[946B0000]            	mov	[next_page], eax ; The first free page pointer
   577                                  				 ; for user programs
   578                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   579                                  	;
   580                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   581                                  	;
   582                                  	
   583                                  	; Enable paging
   584                                  	;
   585 0000048E A1[886B0000]                    mov     eax, [k_page_dir]
   586 00000493 0F22D8                  	mov	cr3, eax
   587 00000496 0F20C0                  	mov	eax, cr0
   588 00000499 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   589 0000049E 0F22C0                  	mov	cr0, eax
   590                                          ;jmp    KCODE:StartPMP
   591                                  
   592 000004A1 EA                      	db 0EAh 		; Opcode for far jump
   593 000004A2 [A8040000]                      dd StartPMP		; 32 bit offset
   594 000004A6 0800                    	dw KCODE		; kernel code segment descriptor
   595                                  
   596                                  StartPMP:
   597                                  	; 06/11//2014
   598                                  	; Clear video page 0
   599                                  	;
   600                                  	; Temporary Code
   601                                  	;
   602                                  	;mov	ecx, 80*25/2
   603 000004A8 66B9E803                	mov	cx, (80*25)/2 ; 02/01/2022
   604 000004AC BF00800B00              	mov	edi, 0B8000h
   605 000004B1 57                      	push	edi ; * ; 02/01/2022
   606 000004B2 31C0                    	xor	eax, eax	; black background, black fore color
   607 000004B4 F3AB                    	rep	stosd
   608                                  	
   609                                  	; 19/08/2014
   610                                  	; Kernel Base Address = 0
   611                                  	; It is mapped to (physically) 0 in the page table.
   612                                  	; So, here is exactly 'StartPMP' address.
   613                                  	;
   614                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   615                                  	;;mov	esi, msgPM
   616                                  	;; 14/08/2015 (kernel version message will appear
   617                                  	;;	       when protected mode and paging is enabled)
   618 000004B6 B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   619 000004B8 BE[E0660000]            	mov	esi, msgKVER
   620 000004BD 5F                      	pop	edi ; * ; 02/01/2022
   621                                  	;mov	edi, 0B8000h ; 27/08/2014
   622                                  	; 20/08/2014
   623 000004BE E892010000              	call	printk
   624                                  
   625                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   626                                  	; // Set IRQ offsets
   627                                  	;
   628                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   629                                  	;
   630                                  					;; ICW1
   631 000004C3 B011                    	mov	al, 11h			; Initialization sequence
   632 000004C5 E620                    	out	20h, al			; 	8259A-1
   633                                  	; jmp 	$+2
   634 000004C7 E6A0                    	out	0A0h, al		; 	8259A-2
   635                                  					;; ICW2
   636 000004C9 B020                    	mov	al, 20h			; Start of hardware ints (20h)
   637 000004CB E621                    	out	21h, al			;	for 8259A-1
   638                                  	; jmp 	$+2
   639 000004CD B028                    	mov	al, 28h			; Start of hardware ints (28h)
   640 000004CF E6A1                    	out	0A1h, al		; 	for 8259A-2
   641                                  					;
   642 000004D1 B004                    	mov	al, 04h			;; ICW3
   643 000004D3 E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   644                                  	; jmp 	$+2
   645 000004D5 B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   646 000004D7 E6A1                    	out	0A1h, al		;
   647                                  					;; ICW4
   648 000004D9 B001                    	mov	al, 01h	 		;
   649 000004DB E621                    	out	21h, al			; 	8086 mode, normal EOI	
   650                                  	; jmp 	$+2
   651 000004DD E6A1                    	out	0A1h, al		;	for both chips.
   652                                  
   653                                  	;mov	al, 0FFh	; mask off all interrupts for now
   654                                  	;out	21h, al
   655                                  	;; jmp 	$+2
   656                                  	;out	0A1h, al
   657                                  
   658                                  	; 02/04/2015
   659                                  	; 26/03/2015 System call (INT 30h) modification
   660                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   661                                  	;
   662                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   663                                  	;  setup_idt:
   664                                  	;
   665                                          ;; 16/02/2015
   666                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   667                                  	; 21/08/2014 (timer_int)
   668 000004DF BE[AC630000]            	mov	esi, ilist
   669 000004E4 8D3D[20690000]          	lea	edi, [idt]
   670                                  	; 26/03/2015
   671 000004EA B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   672                                  	; 02/04/2015
   673 000004EF BB00000800              	mov	ebx,  80000h
   674                                  rp_sidt1:
   675 000004F4 AD                      	lodsd
   676 000004F5 89C2                    	mov	edx, eax
   677 000004F7 66BA008E                	mov	dx, 8E00h
   678 000004FB 6689C3                  	mov	bx, ax
   679 000004FE 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   680                                         			        ; /* interrupt gate - dpl=0, present */
   681 00000500 AB                      	stosd	; selector & offset bits 0-15 	
   682 00000501 89D0                    	mov	eax, edx
   683 00000503 AB                      	stosd	; attributes & offset bits 16-23
   684 00000504 E2EE                    	loop	rp_sidt1
   685 00000506 B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   686                                  rp_sidt2:
   687 00000508 AD                      	lodsd
   688 00000509 21C0                    	and	eax, eax
   689 0000050B 7413                    	jz	short rp_sidt3
   690 0000050D 89C2                    	mov	edx, eax
   691 0000050F 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   692 00000513 6689C3                  	mov	bx, ax
   693 00000516 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   694 00000518 AB                      	stosd
   695 00000519 89D0                    	mov	eax, edx
   696 0000051B AB                      	stosd
   697 0000051C E2EA                    	loop	rp_sidt2
   698 0000051E EB16                    	jmp	short sidt_OK
   699                                  rp_sidt3:
   700 00000520 B8[79090000]            	mov	eax, ignore_int
   701 00000525 89C2                    	mov	edx, eax
   702 00000527 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   703 0000052B 6689C3                  	mov	bx, ax
   704 0000052E 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   705                                  rp_sidt4:
   706 00000530 AB                      	stosd
   707 00000531 92                      	xchg	eax, edx
   708 00000532 AB                      	stosd
   709 00000533 92                      	xchg	edx, eax
   710 00000534 E2FA                    	loop	rp_sidt4
   711                                  sidt_OK: 
   712 00000536 0F011D[A6630000]        	lidt 	[idtd]
   713                                  	;
   714                                  	; TSS descriptor setup ; 24/03/2015
   715 0000053D B8[206B0000]            	mov	eax, task_state_segment
   716 00000542 66A3[9A630000]          	mov	[gdt_tss0], ax
   717 00000548 C1C010                  	rol	eax, 16
   718 0000054B A2[9C630000]            	mov	[gdt_tss1], al
   719 00000550 8825[9F630000]          	mov	[gdt_tss2], ah
   720 00000556 66C705[866B0000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   720 0000055E 00                 
   721                                  		; 
   722                                  		; IO Map Base address (When this address points
   723                                  		; to end of the TSS, CPU does not use IO port 
   724                                  		; permission bit map for RING 3 IO permissions, 
   725                                  		; access to any IO ports in ring 3 will be forbidden.)
   726                                   		;
   727                                  	;mov	[tss.esp0], esp ; TSS offset 4
   728                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   729 0000055F 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   730                                  			 ; occurs (or a system call -software INT- is requested)
   731                                  			 ; while cpu running in ring 3 (in user mode).				
   732                                  			 ; (Kernel stack pointer and segment will be loaded
   733                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   734 00000563 0F00D8                  	ltr	ax  ; Load task register
   735                                  	;
   736                                  esp0_set0:
   737                                  	; 30/07/2015
   738 00000566 8B0D[8C6B0000]          	mov 	ecx, [memory_size] ; memory size in pages
   739 0000056C C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   740 0000056F 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   741                                  			  ; (kernel mode virtual address)
   742 00000575 7605                    	jna	short esp0_set1
   743                                  	;
   744                                  	; If available memory > CORE (end of the 1st 4 MB)
   745                                  	; set stack pointer to CORE
   746                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   747                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   748 00000577 B900004000              	mov	ecx, CORE
   749                                  esp0_set1:
   750 0000057C 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   751                                  esp0_set_ok:
   752                                  	; 30/07/2015 (**tss.esp0**) 
   753 0000057E 8925[246B0000]          	mov	[tss.esp0], esp
   754 00000584 66C705[286B0000]10-             mov     word [tss.ss0], KDATA
   754 0000058C 00                 
   755                                  	; 14/08/2015
   756                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   757                                  	;
   758                                  	;cli	; Disable interrupts (for CPU)
   759                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   760                                  	;
   761 0000058D 30C0                    	xor	al, al		; Enable all hardware interrupts!
   762 0000058F E621                    	out	21h, al		; (IBM PC-AT compatibility)
   763 00000591 EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   764 00000593 E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   765                                  				; (Even if related hardware component
   766                                  				;  does not exist!)
   767                                  	; Enable NMI 
   768 00000595 B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   769 00000597 E670                    	out  	70h, al
   770                                  	; 23/02/2015
   771 00000599 90                      	nop
   772 0000059A E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   773                                  				; for preventing unknown state (!?)
   774                                  	;
   775                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   776                                  	;
   777                                  	; 02/09/2014
   778                                  	;xor	bx, bx
   779                                  	;mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   780                                  	; 27/02/2022	
   781 0000059C 31DB                    	xor	ebx, ebx
   782 0000059E 31D2                    	xor	edx, edx
   783 000005A0 B602                    	mov	dh, 2
   784 000005A2 E8280F0000              	call	set_cpos
   785                                  	;
   786                                  	; 06/11/2014
   787                                  	; Temporary Code
   788                                  	;
   789 000005A7 E8A1100000              	call	memory_info
   790                                  	; 14/08/2015
   791                                  	;call getch ; 28/02/2015
   792                                  drv_init:
   793 000005AC FB                      	sti	; Enable Interrupts 
   794                                  	; 06/02/2015
   795 000005AD 8B15[80660000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   796 000005B3 668B1D[7E660000]        	mov	bx, [fd0_type] ; fd0, fd1
   797                                  	; 22/02/2015
   798 000005BA 6621DB                  	and	bx, bx
   799 000005BD 751B                    	jnz	short di1
   800                                  	;
   801 000005BF 09D2                    	or 	edx, edx
   802 000005C1 7529                    	jnz	short di2
   803                                  	;
   804                                  setup_error:
   805 000005C3 BE[C9670000]            	mov 	esi, setup_error_msg
   806                                  psem:	
   807 000005C8 AC                      	lodsb
   808 000005C9 08C0                    	or	al, al
   809                                  	;jz	short haltx ; 22/02/2015
   810 000005CB 7426                    	jz	short di3
   811 000005CD 56                      	push	esi
   812 000005CE 31DB                    	xor	ebx, ebx ; 0
   813                                  			; Video page 0 (bl=0)
   814 000005D0 B407                    	mov	ah, 07h ; Black background, 
   815                                  			; light gray forecolor
   816 000005D2 E8EE0D0000              	call	write_tty
   817 000005D7 5E                      	pop	esi
   818 000005D8 EBEE                    	jmp	short psem
   819                                  
   820                                  di1:
   821                                  	; supress 'jmp short T6'
   822                                  	;  (activate fdc motor control code)
   823 000005DA 66C705[D6060000]90-     	mov	word [T5], 9090h ; nop
   823 000005E2 90                 
   824                                  	;
   825                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   826                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   827                                  	;stosw
   828                                  	;mov 	ax, cs
   829                                  	;stosw
   830                                  	;; 16/02/2015
   831                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   832                                  	;
   833 000005E3 E8761F0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   834                                  	;
   835 000005E8 09D2                    	or	edx, edx
   836 000005EA 7407                            jz      short di3
   837                                  di2:
   838 000005EC E8B31F0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   839 000005F1 72D0                            jc      short setup_error
   840                                  di3:
   841 000005F3 E829100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   842                                  	;
   843 000005F8 E8CC5C0000              	call	display_disks ; 07/03/2015  (Temporary)
   844                                  ;haltx:
   845                                  	; 14/08/2015
   846                                  	;call	getch ; 22/02/2015
   847 000005FD FB                      	sti	; Enable interrupts (for CPU)
   848                                  	; 14/08/2015
   849                                  	;mov 	ecx, 0FFFFFFFh
   850                                  	; 24/12/2021
   851 000005FE B9FFFF2F00              	mov 	ecx, 02FFFFFh
   852                                  md_info_msg_wait:
   853 00000603 51                      	push 	ecx
   854 00000604 B001                    	mov	al, 1
   855 00000606 8A25[B66B0000]          	mov 	ah, [ptty] ; active (current) video page
   856 0000060C E8175A0000              	call	getc_n
   857 00000611 59                      	pop	ecx
   858 00000612 7502                    	jnz	short md_info_msg_ok
   859 00000614 E2ED                    	loop	md_info_msg_wait
   860                                  md_info_msg_ok:
   861                                  	; 30/06/2015
   862 00000616 E8942C0000              	call	sys_init
   863                                  	;
   864                                  	;jmp 	cpu_reset ; 22/02/2015
   865                                  hang:
   866                                  	; 24/12/2021
   867 0000061B 29C0                    	sub	eax, eax
   868                                  _hang:	
   869                                  	; 23/02/2015
   870                                  	;sti			; Enable interrupts
   871 0000061D F4                      	hlt
   872                                  	;
   873                                  	;nop
   874                                  	;; 03/12/2014
   875                                  	;; 28/08/2014
   876                                  	;mov	ah, 11h
   877                                  	;call	getc
   878                                  	;jz      _c8
   879                                  	;
   880                                  	; 23/02/2015
   881                                  	; 06/02/2015
   882                                  	; 07/09/2014
   883 0000061E 31DB                    	xor	ebx, ebx
   884 00000620 8A1D[B66B0000]          	mov	bl, [ptty]	; active_page
   885 00000626 89DE                    	mov	esi, ebx
   886 00000628 66D1E6                  	shl 	si, 1
   887 0000062B 81C6[B86B0000]          	add	esi, ttychr
   888 00000631 668B06                  	mov	ax, [esi]
   889                                  	;and	ax, ax
   890                                  	;;jz	short _c8
   891                                  	;jz	short hang
   892                                  	; 24/12/2021
   893 00000634 21C0                    	and	eax, eax
   894 00000636 74E5                    	jz	short _hang
   895 00000638 66C7060000              	mov	word [esi], 0
   896 0000063D 80FB03                  	cmp	bl, 3		; Video page 3
   897                                  	;jb	short _c8
   898 00000640 72D9                    	jb	short hang
   899                                  	;	
   900                                  	; 02/09/2014
   901 00000642 B40E                    	mov	ah, 0Eh		; Yellow character 
   902                                  				; on black background
   903                                  	; 24/12/2021 (32 bit reg push-pop)
   904                                  	; 07/09/2014
   905                                  nxtl:
   906 00000644 53                      	push	ebx
   907                                  	;
   908                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   909                                  				; bh = 0 (video mode)
   910                                  				; Retro UNIX 386 v1 - Video Mode 0
   911                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   912 00000645 50                      	push	eax
   913 00000646 E87A0D0000              	call 	write_tty
   914 0000064B 58                      	pop	eax
   915                                  	;pop	bx
   916 0000064C 5B                      	pop	ebx
   917 0000064D 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   918                                  	;jne	short _c8
   919 0000064F 75CA                    	jne	short hang
   920 00000651 B00A                    	mov	al, 0Ah		; next line
   921 00000653 EBEF                    	jmp	short nxtl
   922                                  	
   923                                  ;_c8:
   924                                  ;	; 25/08/2014
   925                                  ;	cli			; Disable interrupts
   926                                  ;	mov	al, [scounter + 1]
   927                                  ;	and	al, al
   928                                  ;	jnz	hang
   929                                  ;	call	rtc_p
   930                                  ;	jmp     hang
   931                                  
   932                                  
   933                                  	; 27/08/2014
   934                                  	; 20/08/2014
   935                                  printk:
   936                                          ;mov    edi, [scr_row]
   937                                  pkl:
   938 00000655 AC                      	lodsb
   939 00000656 08C0                    	or 	al, al
   940 00000658 7404                    	jz	short pkr
   941 0000065A 66AB                    	stosw
   942 0000065C EBF7                    	jmp	short pkl
   943                                  pkr:
   944 0000065E C3                      	retn
   945                                  
   946                                  ; 25/07/2015
   947                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   948                                  ; 17/02/2015
   949                                  ; 06/02/2015 (unix386.s)
   950                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   951                                  ;
   952                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   953                                  ;
   954                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   955                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   956                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   957                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   958                                  ;									       :
   959                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   960                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   961                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   962                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   963                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   964                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   965                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   966                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   967                                  ;-------------------------------------------------------------------------------
   968                                  ;
   969                                  
   970                                  timer_int:	; IRQ 0
   971                                  ;int_08h:	; Timer
   972                                  	; 14/10/2015
   973                                  	; Here, we are simulating system call entry (for task switch)
   974                                  	; (If multitasking is enabled, 
   975                                  	; 'clock' procedure may jump to 'sysrelease')
   976 0000065F 1E                      	push	ds
   977 00000660 06                      	push	es
   978 00000661 0FA0                    	push	fs
   979 00000663 0FA8                    	push	gs
   980 00000665 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   981 00000666 66B91000                	mov     cx, KDATA
   982 0000066A 8ED9                            mov     ds, cx
   983 0000066C 8EC1                            mov     es, cx
   984 0000066E 8EE1                            mov     fs, cx
   985 00000670 8EE9                            mov     gs, cx
   986                                  	;
   987 00000672 0F20D9                  	mov	ecx, cr3
   988 00000675 890D[18070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   989                                  	;
   990 0000067B 3B0D[886B0000]          	cmp 	ecx, [k_page_dir]
   991 00000681 741F                    	je	short T3
   992                                  	;
   993                                  	; timer interrupt has been occurred while OS is in user mode
   994 00000683 A3[4C6F0000]            	mov 	[u.r0], eax
   995 00000688 89E1                    	mov	ecx, esp
   996 0000068A 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   997 0000068D 890D[446F0000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   998 00000693 8925[486F0000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   999                                  	;
  1000 00000699 8B0D[886B0000]          	mov	ecx, [k_page_dir]
  1001 0000069F 0F22D9                  	mov	cr3, ecx
  1002                                  T3:
  1003 000006A2 FB                      	sti				; INTERRUPTS BACK ON
  1004 000006A3 66FF05[046C0000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
  1005 000006AA 7507                    	JNZ	short T4		; GO TO TEST_DAY
  1006 000006AC 66FF05[066C0000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
  1007                                  T4:					; TEST_DAY
  1008 000006B3 66833D[066C0000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
  1009 000006BB 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1010 000006BD 66813D[046C0000]B0-     	CMP	word [TIMER_LOW],0B0H
  1010 000006C5 00                 
  1011 000006C6 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1012                                  
  1013                                  ;-----	TIMER HAS GONE 24 HOURS
  1014                                  	;;SUB	AX,AX
  1015                                  	;MOV	[TIMER_HIGH],AX
  1016                                  	;MOV	[TIMER_LOW],AX
  1017 000006C8 29C0                    	sub	eax, eax
  1018 000006CA A3[046C0000]            	mov	[TIMER_LH], eax
  1019                                  	;	
  1020 000006CF C605[086C0000]01        	MOV	byte [TIMER_OFL],1
  1021                                  
  1022                                  ;-----	TEST FOR DISKETTE TIME OUT
  1023                                  
  1024                                  T5:
  1025                                  	; 23/12/2014
  1026 000006D6 EB1D                    	jmp	short T6		; will be replaced with nop, nop
  1027                                  					; (9090h) if a floppy disk
  1028                                  					; is detected.
  1029                                  	;mov	al,[CS:MOTOR_COUNT]
  1030 000006D8 A0[0B6C0000]            	mov	al, [MOTOR_COUNT]
  1031 000006DD FEC8                    	dec	al
  1032                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
  1033 000006DF A2[0B6C0000]            	mov	[MOTOR_COUNT], al
  1034                                  	;mov	[ORG_MOTOR_COUNT], al
  1035 000006E4 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
  1036 000006E6 B0F0                    	mov 	al,0F0h
  1037                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
  1038 000006E8 2005[0A6C0000]          	and	[MOTOR_STATUS], al
  1039                                  	;and	[ORG_MOTOR_STATUS], al
  1040 000006EE B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
  1041                                  					; bit 2 = enable controller
  1042                                  					;	1 = normal operation
  1043                                  					;	0 = reset	
  1044                                  					; bit 0, 1 = drive select
  1045                                  					; bit 4-7 = motor running bits 
  1046 000006F0 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
  1047 000006F4 EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1048                                  T6:	
  1049                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1050                                  					; TIMER TICK INTERRUPT
  1051                                  	;;inc	word [wait_count] ;;27/02/2015
  1052                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1053                                  	;;;;cli
  1054                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1055 000006F5 FF15[10070000]          	call	[x_timer] ; 14/05/2015
  1056                                  T7:
  1057                                  	; 14/10/2015
  1058 000006FB B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1059 000006FD FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1060 000006FE E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1061                                  	;
  1062 00000700 A1[18070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1063 00000705 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1064                                  	;
  1065 00000708 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1066                                  	;
  1067 00000709 0FA9                    	pop	gs
  1068 0000070B 0FA1                    	pop	fs
  1069 0000070D 07                      	pop	es
  1070 0000070E 1F                      	pop	ds
  1071 0000070F CF                      	iretd	; return from interrupt
  1072                                  
  1073                                  
  1074                                  ; ////////////////
  1075                                  
  1076                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1077                                  x_timer:
  1078 00000710 [1C070000]              	dd 	u_timer			; 14/05/2015
  1079                                  	;dd	clock
  1080                                  
  1081                                  ; 26/02/2022 - Real time clock (digital) output demo (sys emt)
  1082                                  x_rtci:
  1083 00000714 [520A0000]              	dd	rtc_p	; (temporary demo code)	; 26/02/2022
  1084                                  
  1085                                  ; 14/10/2015
  1086 00000718 00000000                cr3reg: dd 0
  1087                                  
  1088                                  	; 24/12/2021 - Retro UNIX 386 v1.1
  1089                                  	; 06/02/2015
  1090                                  	; 07/09/2014
  1091                                  	; 21/08/2014
  1092                                  u_timer:
  1093                                  ;timer_int:	; IRQ 0
  1094                                  	; 06/02/2015
  1095                                  	;push	eax
  1096                                  	;push	edx
  1097                                  	;push	ecx
  1098                                  	;push	ebx
  1099                                  	;push	ds
  1100                                  	;push	es
  1101                                  	;mov	eax, KDATA
  1102                                  	;mov	ds, ax
  1103                                  	;mov	es, ax
  1104 0000071C FF05[CC6B0000]          	inc	dword [tcount]
  1105 00000722 BB[52670000]            	mov	ebx, tcountstr + 4
  1106                                  	;mov	ax, [tcount]
  1107                                  	; 24/12/2021
  1108 00000727 A1[CC6B0000]            	mov	eax, [tcount]
  1109 0000072C B90A000000              	mov	ecx, 10
  1110                                  rp_divtcnt:
  1111 00000731 31D2                    	xor	edx, edx
  1112 00000733 F7F1                    	div	ecx
  1113 00000735 80C230                  	add	dl, 30h
  1114 00000738 8813                    	mov	[ebx], dl
  1115                                  	;or	ax, ax
  1116                                  	; 24/12/2021
  1117 0000073A 09C0                    	or	eax, eax
  1118 0000073C 7403                    	jz	short print_lzero
  1119 0000073E 4B                      	dec	ebx
  1120 0000073F EBF0                    	jmp	short rp_divtcnt
  1121                                  print_lzero:
  1122 00000741 81FB[4E670000]          	cmp	ebx, tcountstr
  1123 00000747 7606                    	jna	short print_tcount
  1124 00000749 4B                      	dec	ebx
  1125 0000074A C60330                   	mov	byte [ebx], 30h
  1126 0000074D EBF2                    	jmp	short print_lzero
  1127                                  print_tcount:
  1128 0000074F 56                      	push	esi
  1129 00000750 57                      	push	edi
  1130 00000751 BE[2A670000]            	mov	esi, timer_msg ; Timer interrupt message
  1131                                  	; 07/09/2014
  1132                                  	;mov	bx, 1	; Video page 1
  1133                                  	; 24/12/2021
  1134 00000756 29DB                    	sub	ebx, ebx
  1135                                  	;inc	bl ; ebx = 1
  1136                                  	; 02/01/2022
  1137 00000758 B306                    	mov	bl, 6	; Video page 6
  1138                                  ptmsg:
  1139 0000075A AC                      	lodsb
  1140 0000075B 08C0                    	or	al, al
  1141 0000075D 740D                    	jz	short ptmsg_ok
  1142 0000075F 56                      	push	esi
  1143                                  	;push	bx
  1144                                  	; 24/12/2021
  1145 00000760 53                              push	ebx
  1146 00000761 B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1147 00000763 E85D0C0000              	call 	write_tty
  1148                                  	;pop	bx
  1149                                  	; 24/12/2021
  1150 00000768 5B                      	pop	ebx
  1151 00000769 5E                      	pop	esi
  1152 0000076A EBEE                    	jmp	short ptmsg
  1153                                  	;; 27/08/2014
  1154                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1155                                  	;call	printk
  1156                                  	;
  1157                                  ptmsg_ok:
  1158                                  	; 07/09/2014
  1159                                  	;xor	dx, dx		; column 0, row 0
  1160                                  	; 24/12/2021
  1161 0000076C 31D2                    	xor	edx, edx
  1162 0000076E E85C0D0000              	call	set_cpos	; set cursor position to 0,0 
  1163                                  	; 23/02/2015
  1164                                  	; 25/08/2014
  1165                                  	;mov	ebx, scounter		; (seconds counter)
  1166                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1167                                  ;	dec	byte [scounter+1]
  1168                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1169                                  ;	jns	short u_timer_retn
  1170                                  	; 26/02/2015
  1171                                  ;	call	rtc_p
  1172                                  ;	mov	ebx, scounter		; (seconds counter)
  1173                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1174                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1175                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1176                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1177                                  ;	mov	byte [ebx], 5
  1178                                  ;	inc	byte [ebx+1] ; 19
  1179                                  ;;timer_eoi:
  1180                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1181                                  ;;	out	20h, al	; 8259 PORT
  1182                                  	;
  1183                                  ;u_timer_retn:  ; 06/02/2015
  1184 00000773 5F                      	pop	edi
  1185 00000774 5E                      	pop	esi
  1186                                  	;pop	es
  1187                                  	;pop	ds
  1188                                  	;pop	ebx
  1189                                  	;pop	ecx
  1190                                  	;pop	edx
  1191                                  	;pop	eax
  1192                                  	;iret
  1193 00000775 C3                      	retn	; 06/02/2015
  1194                                  
  1195                                  	; 28/08/2014
  1196                                  irq0:
  1197 00000776 6A00                            push 	dword 0
  1198 00000778 EB48                    	jmp	short which_irq
  1199                                  irq1:
  1200 0000077A 6A01                            push 	dword 1
  1201 0000077C EB44                    	jmp	short which_irq
  1202                                  irq2:
  1203 0000077E 6A02                            push 	dword 2
  1204 00000780 EB40                    	jmp	short which_irq
  1205                                  irq3:
  1206                                  	; 20/11/2015
  1207                                  	; 24/10/2015
  1208 00000782 2EFF15[CA390000]        	call	dword [cs:com2_irq3]
  1209 00000789 6A03                    	push 	dword 3
  1210 0000078B EB35                    	jmp	short which_irq
  1211                                  irq4:
  1212                                  	; 20/11/2015
  1213                                  	; 24/10/2015
  1214 0000078D 2EFF15[C6390000]        	call	dword [cs:com1_irq4]
  1215 00000794 6A04                            push 	dword 4
  1216 00000796 EB2A                    	jmp	short which_irq
  1217                                  irq5:
  1218 00000798 6A05                            push 	dword 5
  1219 0000079A EB26                    	jmp	short which_irq
  1220                                  irq6:
  1221 0000079C 6A06                            push 	dword 6
  1222 0000079E EB22                    	jmp	short which_irq
  1223                                  irq7:
  1224 000007A0 6A07                            push 	dword 7
  1225 000007A2 EB1E                    	jmp	short which_irq
  1226                                  irq8:
  1227 000007A4 6A08                            push 	dword 8
  1228 000007A6 EB1A                    	jmp	short which_irq
  1229                                  irq9:
  1230 000007A8 6A09                            push 	dword 9
  1231 000007AA EB16                    	jmp	short which_irq
  1232                                  irq10:
  1233 000007AC 6A0A                            push 	dword 10
  1234 000007AE EB12                    	jmp	short which_irq
  1235                                  irq11:
  1236 000007B0 6A0B                            push 	dword 11
  1237 000007B2 EB0E                    	jmp	short which_irq
  1238                                  irq12:
  1239 000007B4 6A0C                            push 	dword 12
  1240 000007B6 EB0A                    	jmp	short which_irq
  1241                                  irq13:
  1242 000007B8 6A0D                            push 	dword 13
  1243 000007BA EB06                    	jmp	short which_irq
  1244                                  irq14:
  1245 000007BC 6A0E                            push 	dword 14
  1246 000007BE EB02                    	jmp	short which_irq
  1247                                  irq15:
  1248 000007C0 6A0F                            push 	dword 15
  1249                                  	;jmp	short which_irq
  1250                                  
  1251                                  	; 19/10/2015
  1252                                  	; 29/08/2014
  1253                                  	; 21/08/2014
  1254                                  which_irq:
  1255 000007C2 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1256 000007C5 53                      	push	ebx
  1257 000007C6 56                      	push	esi
  1258 000007C7 57                      	push	edi
  1259 000007C8 1E                      	push 	ds
  1260 000007C9 06                      	push 	es
  1261                                  	;
  1262 000007CA 88C3                    	mov	bl, al
  1263                                  	;
  1264 000007CC B810000000              	mov	eax, KDATA
  1265 000007D1 8ED8                    	mov	ds, ax
  1266 000007D3 8EC0                    	mov	es, ax
  1267                                  	; 19/10/2015
  1268 000007D5 FC                      	cld
  1269                                          ; 27/08/2014
  1270 000007D6 8105[D8660000]A000-             add     dword [scr_row], 0A0h
  1270 000007DE 0000               
  1271                                  	;
  1272 000007E0 B417                    	mov	ah, 17h	; blue (1) background, 
  1273                                  			; light gray (7) forecolor
  1274 000007E2 8B3D[D8660000]                  mov     edi, [scr_row]
  1275 000007E8 B049                    	mov	al, 'I'
  1276 000007EA 66AB                    	stosw
  1277 000007EC B052                    	mov	al, 'R'
  1278 000007EE 66AB                    	stosw
  1279 000007F0 B051                    	mov	al, 'Q'
  1280 000007F2 66AB                    	stosw
  1281 000007F4 B020                    	mov	al, ' '
  1282 000007F6 66AB                    	stosw
  1283 000007F8 88D8                    	mov	al, bl
  1284 000007FA 3C0A                    	cmp	al, 10
  1285 000007FC 7208                    	jb	short iix
  1286 000007FE B031                    	mov	al, '1'
  1287 00000800 66AB                    	stosw
  1288 00000802 88D8                    	mov	al, bl
  1289 00000804 2C0A                    	sub	al, 10
  1290                                  iix:
  1291 00000806 0430                    	add	al, '0'
  1292 00000808 66AB                    	stosw
  1293 0000080A B020                    	mov	al, ' '
  1294 0000080C 66AB                    	stosw
  1295 0000080E B021                    	mov	al, '!'
  1296 00000810 66AB                    	stosw
  1297 00000812 B020                    	mov	al, ' '
  1298 00000814 66AB                    	stosw
  1299                                  	; 23/02/2015
  1300 00000816 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1301                                  	;jna	iiret
  1302                                  	; 02/01/2022
  1303 00000819 7604                    	jna	short iiz
  1304                                  iiy:
  1305 0000081B B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1306 0000081D E6A0                    	out	0A0h, al ; the 2nd 8259
  1307                                  iiz:
  1308 0000081F E983010000              	jmp     iiret
  1309                                  	;
  1310                                  	; 22/08/2014
  1311                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1312                                  	;out	20h, al	; 8259 PORT
  1313                                  	;
  1314                                  	;pop	es
  1315                                  	;pop	ds
  1316                                  	;pop	edi
  1317                                  	;pop	esi
  1318                                  	;pop	ebx
  1319                                  	;pop 	eax
  1320                                  	;iret
  1321                                  
  1322                                  	; 02/04/2015
  1323                                  	; 25/08/2014
  1324                                  exc0:
  1325 00000824 6A00                            push 	dword 0
  1326 00000826 E990000000                      jmp     cpu_except
  1327                                  exc1:
  1328 0000082B 6A01                            push 	dword 1
  1329 0000082D E989000000                      jmp     cpu_except
  1330                                  exc2:
  1331 00000832 6A02                            push 	dword 2
  1332 00000834 E982000000                      jmp     cpu_except
  1333                                  exc3:
  1334 00000839 6A03                            push 	dword 3
  1335 0000083B EB7E                            jmp     cpu_except
  1336                                  exc4:
  1337 0000083D 6A04                            push 	dword 4
  1338 0000083F EB7A                            jmp     cpu_except
  1339                                  exc5:
  1340 00000841 6A05                            push 	dword 5
  1341 00000843 EB76                            jmp     cpu_except
  1342                                  exc6:
  1343 00000845 6A06                            push 	dword 6
  1344 00000847 EB72                            jmp     cpu_except
  1345                                  exc7:
  1346 00000849 6A07                            push 	dword 7
  1347 0000084B EB6E                            jmp     cpu_except
  1348                                  exc8:
  1349                                  	; [esp] = Error code
  1350 0000084D 6A08                            push 	dword 8
  1351 0000084F EB5C                            jmp     cpu_except_en
  1352                                  exc9:
  1353 00000851 6A09                            push 	dword 9
  1354 00000853 EB66                            jmp     cpu_except
  1355                                  exc10:
  1356                                  	; [esp] = Error code
  1357 00000855 6A0A                            push 	dword 10
  1358 00000857 EB54                            jmp     cpu_except_en
  1359                                  exc11:
  1360                                  	; [esp] = Error code
  1361 00000859 6A0B                            push 	dword 11
  1362 0000085B EB50                            jmp     cpu_except_en
  1363                                  exc12:
  1364                                  	; [esp] = Error code
  1365 0000085D 6A0C                            push 	dword 12
  1366 0000085F EB4C                            jmp     cpu_except_en
  1367                                  exc13:
  1368                                  	; [esp] = Error code
  1369 00000861 6A0D                            push 	dword 13
  1370 00000863 EB48                            jmp     cpu_except_en
  1371                                  exc14:
  1372                                  	; [esp] = Error code
  1373 00000865 6A0E                            push 	dword 14
  1374 00000867 EB44                    	jmp	short cpu_except_en
  1375                                  exc15:
  1376 00000869 6A0F                            push 	dword 15
  1377 0000086B EB4E                            jmp     cpu_except
  1378                                  exc16:
  1379 0000086D 6A10                            push 	dword 16
  1380 0000086F EB4A                            jmp     cpu_except
  1381                                  exc17:
  1382                                  	; [esp] = Error code
  1383 00000871 6A11                            push 	dword 17
  1384 00000873 EB38                    	jmp	short cpu_except_en
  1385                                  exc18:
  1386 00000875 6A12                            push 	dword 18
  1387 00000877 EB42                    	jmp	short cpu_except
  1388                                  exc19:
  1389 00000879 6A13                            push 	dword 19
  1390 0000087B EB3E                    	jmp	short cpu_except
  1391                                  exc20:
  1392 0000087D 6A14                            push 	dword 20
  1393 0000087F EB3A                    	jmp	short cpu_except
  1394                                  exc21:
  1395 00000881 6A15                            push 	dword 21
  1396 00000883 EB36                    	jmp	short cpu_except
  1397                                  exc22:
  1398 00000885 6A16                            push 	dword 22
  1399 00000887 EB32                    	jmp	short cpu_except
  1400                                  exc23:
  1401 00000889 6A17                            push 	dword 23
  1402 0000088B EB2E                    	jmp	short cpu_except
  1403                                  exc24:
  1404 0000088D 6A18                            push 	dword 24
  1405 0000088F EB2A                    	jmp	short cpu_except
  1406                                  exc25:
  1407 00000891 6A19                            push 	dword 25
  1408 00000893 EB26                    	jmp	short cpu_except
  1409                                  exc26:
  1410 00000895 6A1A                            push 	dword 26
  1411 00000897 EB22                    	jmp	short cpu_except
  1412                                  exc27:
  1413 00000899 6A1B                            push 	dword 27
  1414 0000089B EB1E                    	jmp	short cpu_except
  1415                                  exc28:
  1416 0000089D 6A1C                            push 	dword 28
  1417 0000089F EB1A                    	jmp	short cpu_except
  1418                                  exc29:
  1419 000008A1 6A1D                            push 	dword 29
  1420 000008A3 EB16                    	jmp	short cpu_except
  1421                                  exc30:
  1422 000008A5 6A1E                            push 	dword 30
  1423 000008A7 EB04                    	jmp	short cpu_except_en
  1424                                  exc31:
  1425 000008A9 6A1F                            push 	dword 31
  1426 000008AB EB0E                            jmp     short cpu_except
  1427                                  
  1428                                  	; 02/01/2022
  1429                                  	; 19/10/2015
  1430                                  	; 19/09/2015
  1431                                  	; 01/09/2015
  1432                                  	; 28/08/2015
  1433                                  	; 28/08/2014
  1434                                  cpu_except_en:
  1435 000008AD 87442404                	xchg	eax, [esp+4] ; Error code
  1436 000008B1 36A3[386C0000]          	mov	[ss:error_code], eax
  1437 000008B7 58                      	pop	eax  ; Exception number
  1438 000008B8 870424                  	xchg	eax, [esp]
  1439                                  		; eax = eax before exception
  1440                                  		; [esp] -> exception number
  1441                                  		; [esp+4] -> EIP to return
  1442                                  	; 19/10/2015
  1443                                  	; 19/09/2015
  1444                                  	; 01/09/2015
  1445                                  	; 28/08/2015
  1446                                  	; 29/08/2014
  1447                                  	; 28/08/2014
  1448                                  	; 25/08/2014
  1449                                  	; 21/08/2014
  1450                                  cpu_except:	; CPU Exceptions
  1451 000008BB FC                      	cld
  1452 000008BC 870424                  	xchg	eax, [esp] 
  1453                                  		; eax = Exception number
  1454                                  		; [esp] = eax (before exception)
  1455 000008BF 53                      	push	ebx
  1456 000008C0 56                      	push	esi
  1457 000008C1 57                      	push	edi
  1458 000008C2 1E                      	push 	ds
  1459 000008C3 06                      	push 	es
  1460                                  	; 28/08/2015
  1461 000008C4 66BB1000                	mov	bx, KDATA
  1462 000008C8 8EDB                    	mov	ds, bx
  1463 000008CA 8EC3                    	mov	es, bx
  1464 000008CC 0F20DB                  	mov	ebx, cr3
  1465 000008CF 53                      	push	ebx ; (*) page directory
  1466                                  	; 19/10/2015
  1467 000008D0 FC                      	cld
  1468                                  	; 25/03/2015
  1469 000008D1 8B1D[886B0000]          	mov	ebx, [k_page_dir]
  1470 000008D7 0F22DB                  	mov	cr3, ebx
  1471                                  	; 28/08/2015
  1472 000008DA 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT
  1473 000008DD 7513                    	jne	short cpu_except_nfp
  1474 000008DF E885270000              	call	page_fault_handler
  1475 000008E4 21C0                    	and 	eax, eax
  1476                                  	;jz	iiretp ; 01/09/2015
  1477                                  	; 02/01/2022
  1478 000008E6 7505                    	jnz	short cpu_except_pf
  1479 000008E8 E9B6000000              	jmp	iiretp
  1480                                  cpu_except_pf:
  1481 000008ED B80E000000              	mov	eax, 0Eh ; 14
  1482                                  cpu_except_nfp:
  1483                                  	; 02/04/2015
  1484 000008F2 BB[1B060000]            	mov	ebx, hang
  1485 000008F7 875C241C                	xchg	ebx, [esp+28]
  1486                                  		; EIP (points to instruction which faults)
  1487                                  	  	; New EIP (hang)
  1488 000008FB 891D[3C6C0000]          	mov	[FaultOffset], ebx
  1489 00000901 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1490 00000909 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1491                                  	;
  1492 00000911 88C4                    	mov	ah, al
  1493 00000913 240F                    	and	al, 0Fh
  1494 00000915 3C09                    	cmp	al, 9
  1495 00000917 7602                    	jna	short h1ok
  1496 00000919 0407                    	add	al, 'A'-':'
  1497                                  h1ok:
  1498 0000091B D0EC                    	shr	ah, 1
  1499 0000091D D0EC                    	shr	ah, 1
  1500 0000091F D0EC                    	shr	ah, 1
  1501 00000921 D0EC                    	shr	ah, 1
  1502 00000923 80FC09                  	cmp	ah, 9
  1503 00000926 7603                    	jna	short h2ok
  1504 00000928 80C407                  	add	ah, 'A'-':'
  1505                                  h2ok:	
  1506 0000092B 86E0                    	xchg 	ah, al	
  1507 0000092D 66053030                	add	ax, '00'
  1508 00000931 66A3[66670000]          	mov	[excnstr], ax
  1509                                  	;
  1510                                  	; 29/08/2014
  1511 00000937 A1[3C6C0000]            	mov	eax, [FaultOffset]
  1512 0000093C 51                      	push	ecx
  1513 0000093D 52                      	push	edx
  1514 0000093E 89E3                    	mov	ebx, esp
  1515                                  	; 28/08/2015
  1516 00000940 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1517                                  			  ; to hexadecimal string
  1518                                  	;mov	ecx, 10	    ; divisor to convert
  1519                                  			    ; binary number to decimal string
  1520                                  b2d1:
  1521 00000945 31D2                    	xor	edx, edx
  1522 00000947 F7F1                    	div	ecx
  1523                                  	;push	dx
  1524                                  	; 02/01/2022
  1525 00000949 52                      	push	edx
  1526 0000094A 39C8                    	cmp	eax, ecx
  1527 0000094C 73F7                    	jnb	short b2d1
  1528 0000094E BF[71670000]            	mov	edi, EIPstr ; EIP value
  1529                                  			    ; points to instruction which faults
  1530                                  	; 28/08/2015
  1531 00000953 89C2                    	mov	edx, eax
  1532                                  b2d2:
  1533                                  	;add	al, '0'
  1534 00000955 8A82[05170000]          	mov	al, [edx+hexchrs]
  1535 0000095B AA                      	stosb		    ; write hexadecimal digit to its place
  1536 0000095C 39E3                    	cmp	ebx, esp
  1537 0000095E 7605                    	jna	short b2d3
  1538                                  	; 02/01/2022
  1539 00000960 58                      	pop	eax
  1540                                  	;pop	ax
  1541 00000961 88C2                    	mov	dl, al
  1542 00000963 EBF0                    	jmp	short b2d2
  1543                                  b2d3:
  1544 00000965 B068                    	mov 	al, 'h' ; 28/08/2015
  1545 00000967 AA                      	stosb
  1546 00000968 B020                    	mov	al, 20h	    ; space
  1547 0000096A AA                      	stosb
  1548 0000096B 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1549 0000096D AA                      	stosb
  1550                                  	;
  1551 0000096E 5A                      	pop	edx
  1552 0000096F 59                      	pop	ecx
  1553                                  	;
  1554 00000970 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1555                                  			; white (F) forecolor
  1556 00000972 BE[56670000]            	mov	esi, exc_msg ; message offset
  1557                                  	;
  1558 00000977 EB11                    	jmp	short piemsg
  1559                                  	;
  1560                                          ;add    dword [scr_row], 0A0h
  1561                                          ;mov    edi, [scr_row]
  1562                                          ;
  1563                                  	;call 	printk
  1564                                  	;
  1565                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1566                                  	;out	20h, al	; 8259 PORT
  1567                                  	;
  1568                                  	;pop	es
  1569                                  	;pop	ds
  1570                                  	;pop	edi
  1571                                  	;pop	esi
  1572                                  	;pop 	eax
  1573                                  	;iret
  1574                                  	
  1575                                  	; 28/08/2015
  1576                                  	; 23/02/2015
  1577                                  	; 20/08/2014
  1578                                  ignore_int:
  1579 00000979 50                      	push	eax
  1580 0000097A 53                      	push	ebx ; 23/02/2015
  1581 0000097B 56                      	push	esi
  1582 0000097C 57                      	push	edi
  1583 0000097D 1E                      	push 	ds
  1584 0000097E 06                      	push 	es
  1585                                  	; 28/08/2015
  1586 0000097F 0F20D8                  	mov	eax, cr3
  1587 00000982 50                      	push	eax ; (*) page directory
  1588                                  	;
  1589 00000983 B467                    	mov	ah, 67h	; brown (6) background, 
  1590                                  			; light gray (7) forecolor
  1591 00000985 BE[14670000]            	mov	esi, int_msg ; message offset
  1592                                  piemsg:
  1593                                          ; 27/08/2014
  1594 0000098A 8105[D8660000]A000-             add     dword [scr_row], 0A0h
  1594 00000992 0000               
  1595 00000994 8B3D[D8660000]                  mov     edi, [scr_row]
  1596                                          ;
  1597 0000099A E8B6FCFFFF              	call 	printk
  1598                                  	;
  1599                                  	; 23/02/2015
  1600 0000099F B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1601 000009A1 E6A0                    	out	0A0h, al ; the 2nd 8259
  1602                                  iiretp: ; 01/09/2015
  1603                                  	; 28/08/2015
  1604 000009A3 58                      	pop	eax ; (*) page directory
  1605 000009A4 0F22D8                  	mov	cr3, eax
  1606                                  	;
  1607                                  iiret:
  1608                                  	; 22/08/2014
  1609 000009A7 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1610 000009A9 E620                    	out	20h, al	; 8259 PORT
  1611                                  	;
  1612 000009AB 07                      	pop	es
  1613 000009AC 1F                      	pop	ds
  1614 000009AD 5F                      	pop	edi
  1615 000009AE 5E                      	pop	esi
  1616 000009AF 5B                      	pop	ebx ; 29/08/2014
  1617 000009B0 58                      	pop 	eax
  1618 000009B1 CF                      	iretd
  1619                                  
  1620                                  	; 26/02/2022
  1621                                  	; 26/02/2015
  1622                                  	; 07/09/2014
  1623                                  	; 25/08/2014
  1624                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1625                                  	; 22/08/2014
  1626 000009B2 50                      	push	eax
  1627 000009B3 53                      	push	ebx ; 29/08/2014
  1628 000009B4 56                      	push	esi
  1629 000009B5 57                      	push	edi
  1630 000009B6 1E                      	push 	ds
  1631 000009B7 06                      	push 	es
  1632                                  	;
  1633 000009B8 B810000000              	mov	eax, KDATA
  1634 000009BD 8ED8                    	mov	ds, ax
  1635 000009BF 8EC0                    	mov	es, ax
  1636                                  	;
  1637                                  	; 25/08/2014
  1638                                  	;call	rtc_p
  1639                                  	; 26/02/2022
  1640 000009C1 FF15[14070000]          	call	[x_rtci]
  1641                                  	;
  1642                                  	; 22/02/2015 - dsectpm.s
  1643                                  	; [ source: http://wiki.osdev.org/RTC ]
  1644                                  	; read status register C to complete procedure
  1645                                  	;(it is needed to get a next IRQ 8) 
  1646 000009C7 B00C                    	mov	al, 0Ch ; 
  1647 000009C9 E670                    	out	70h, al ; select register C
  1648 000009CB 90                      	nop
  1649 000009CC E471                    	in	al, 71h ; just throw away contents
  1650                                  	; 22/02/2015
  1651 000009CE B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1652 000009D0 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1653                                  	;
  1654 000009D2 EBD3                    	jmp	short iiret	
  1655                                  
  1656                                  	; 22/08/2014
  1657                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1658                                  	; (INT 1Ah)
  1659                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1660                                  time_of_day:
  1661 000009D4 E866010000              	call	UPD_IPR		; WAIT TILL UPDATE NOT IN PROGRESS
  1662 000009D9 726F                            jc      short rtc_retn 
  1663 000009DB B000                    	mov	al, CMOS_SECONDS
  1664 000009DD E847010000              	call	CMOS_READ
  1665 000009E2 A2[FC6B0000]            	mov	[time_seconds], al 
  1666 000009E7 B002                    	mov	al, CMOS_MINUTES
  1667 000009E9 E83B010000              	call	CMOS_READ
  1668 000009EE A2[FD6B0000]            	mov	[time_minutes], al 
  1669 000009F3 B004                    	mov	al, CMOS_HOURS
  1670 000009F5 E82F010000              	call	CMOS_READ
  1671 000009FA A2[FE6B0000]                    mov     [time_hours], al
  1672 000009FF B006                    	mov	al, CMOS_DAY_WEEK 
  1673 00000A01 E823010000              	call	CMOS_READ
  1674 00000A06 A2[FF6B0000]            	mov	[date_wday], al
  1675 00000A0B B007                     	mov	al, CMOS_DAY_MONTH
  1676 00000A0D E817010000              	call	CMOS_READ
  1677 00000A12 A2[006C0000]            	mov	[date_day], al
  1678 00000A17 B008                    	mov	al, CMOS_MONTH
  1679 00000A19 E80B010000              	call	CMOS_READ
  1680 00000A1E A2[016C0000]            	mov	[date_month], al
  1681 00000A23 B009                    	mov	al, CMOS_YEAR
  1682 00000A25 E8FF000000              	call	CMOS_READ
  1683 00000A2A A2[026C0000]            	mov	[date_year], al
  1684 00000A2F B032                    	mov	al, CMOS_CENTURY
  1685 00000A31 E8F3000000              	call	CMOS_READ
  1686 00000A36 A2[036C0000]            	mov	[date_century], al
  1687                                  	;
  1688 00000A3B B000                    	mov	al, CMOS_SECONDS
  1689 00000A3D E8E7000000              	call 	CMOS_READ
  1690 00000A42 3A05[FC6B0000]          	cmp	al, [time_seconds]
  1691 00000A48 758A                    	jne	short time_of_day
  1692                                  
  1693                                  rtc_retn:
  1694 00000A4A C3                      	retn
  1695                                  
  1696                                  rtci_default:
  1697                                  	; 26/02/2022 (Temporary!)
  1698                                  	; (default real time clock handler in multitasking mode)
  1699                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1700 00000A4B FF05[446C0000]          	inc	dword [rtc_ticks] ; real time clock counter
  1701                                  			; (not used in anywhere of kernel for now!)
  1702 00000A51 C3                      	retn
  1703                                  
  1704                                  rtc_p:	
  1705                                  	; 07/09/2014
  1706                                  	; 29/08/2014
  1707                                  	; 27/08/2014
  1708                                  	; 25/08/2014
  1709                                   	; Print Real Time Clock content
  1710                                  	;
  1711                                  	;
  1712 00000A52 E87DFFFFFF              	call	time_of_day
  1713 00000A57 72F1                    	jc	short rtc_retn
  1714                                  	;
  1715 00000A59 3A05[C8670000]          	cmp	al, [ptime_seconds]
  1716 00000A5F 74E9                            je      short rtc_retn ; 29/08/2014
  1717                                  	;
  1718 00000A61 A2[C8670000]            	mov	[ptime_seconds], al
  1719                                  	;
  1720 00000A66 A0[036C0000]            	mov	al, [date_century]
  1721 00000A6B E8EA000000              	call	bcd_to_ascii
  1722 00000A70 66A3[95670000]          	mov	[datestr+6], ax
  1723 00000A76 A0[026C0000]            	mov	al, [date_year]
  1724 00000A7B E8DA000000              	call	bcd_to_ascii
  1725 00000A80 66A3[97670000]          	mov	[datestr+8], ax
  1726 00000A86 A0[016C0000]            	mov	al, [date_month]
  1727 00000A8B E8CA000000              	call	bcd_to_ascii
  1728 00000A90 66A3[92670000]          	mov	[datestr+3], ax
  1729 00000A96 A0[006C0000]            	mov	al, [date_day]
  1730 00000A9B E8BA000000              	call	bcd_to_ascii
  1731 00000AA0 66A3[8F670000]          	mov	[datestr], ax
  1732                                  	;
  1733 00000AA6 0FB61D[FF6B0000]        	movzx	ebx, byte [date_wday]
  1734 00000AAD C0E302                  	shl 	bl, 2
  1735 00000AB0 81C3[A8670000]          	add	ebx, daytmp
  1736 00000AB6 8B03                    	mov	eax, [ebx]
  1737 00000AB8 A3[9A670000]            	mov	[daystr], eax
  1738                                  	;
  1739 00000ABD A0[FE6B0000]            	mov	al, [time_hours]
  1740 00000AC2 E893000000              	call	bcd_to_ascii
  1741 00000AC7 66A3[9E670000]          	mov	[timestr], ax
  1742 00000ACD A0[FD6B0000]            	mov	al, [time_minutes]
  1743 00000AD2 E883000000              	call	bcd_to_ascii
  1744 00000AD7 66A3[A1670000]          	mov	[timestr+3], ax
  1745 00000ADD A0[FC6B0000]            	mov	al, [time_seconds]
  1746 00000AE2 E873000000              	call	bcd_to_ascii
  1747 00000AE7 66A3[A4670000]          	mov	[timestr+6], ax
  1748                                  	;		
  1749 00000AED BE[7D670000]            	mov	esi, rtc_msg ; message offset
  1750                                  	; 23/02/2015
  1751 00000AF2 52                      	push	edx
  1752 00000AF3 51                      	push	ecx
  1753                                  	; 07/09/2014
  1754                                  	;mov	bx, 2	; Video page 2
  1755                                  	; 02/01/2022
  1756 00000AF4 29DB                    	sub	ebx, ebx
  1757 00000AF6 B307                    	mov	bl, 7	; Video page 7 
  1758                                  prtmsg:
  1759 00000AF8 AC                      	lodsb
  1760 00000AF9 08C0                    	or	al, al
  1761 00000AFB 740D                    	jz	short prtmsg_ok
  1762 00000AFD 56                      	push	esi
  1763                                  	; 02/01/2022
  1764 00000AFE 53                      	push	ebx
  1765                                  	;push	bx
  1766 00000AFF B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1767                                  			; white (F) forecolor
  1768 00000B01 E8BF080000              	call 	write_tty
  1769                                  	;pop	bx
  1770                                  	; 02/01/2022
  1771 00000B06 5B                      	pop	ebx
  1772 00000B07 5E                      	pop	esi
  1773 00000B08 EBEE                    	jmp	short prtmsg
  1774                                  	;
  1775                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1776                                  	;call	printk
  1777                                  prtmsg_ok:
  1778                                  	; 07/09/2014
  1779                                  	;xor	dx, dx		; column 0, row 0
  1780                                  	; 02/01/2022
  1781 00000B0A 31D2                    	xor	edx, edx
  1782 00000B0C E8BE090000              	call	set_cpos	; set curspor position to 0,0 
  1783                                  	; 23/02/2015
  1784 00000B11 59                      	pop	ecx
  1785 00000B12 5A                      	pop	edx
  1786 00000B13 C3                      	retn
  1787                                  
  1788                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1789                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1790                                  default_irq7:
  1791                                  	; 24/12/2021
  1792                                  	;push	ax
  1793 00000B14 50                      	push	eax
  1794 00000B15 B00B                    	mov	al, 0Bh  ; In-Service register
  1795 00000B17 E620                    	out	20h, al
  1796 00000B19 EB00                            jmp short $+2
  1797 00000B1B EB00                    	jmp short $+2
  1798 00000B1D E420                    	in	al, 20h
  1799 00000B1F 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1800 00000B21 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1801 00000B23 B020                            mov     al, 20h ; EOI
  1802 00000B25 E620                    	out	20h, al 
  1803                                  irq7_iret:
  1804                                  	;pop	ax
  1805                                  	; 24/12/2021
  1806 00000B27 58                      	pop	eax
  1807 00000B28 CF                      	iretd	
  1808                                  	
  1809                                  	; 24/12/2021
  1810                                  	; 22/08/2014
  1811                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1812                                  CMOS_READ:
  1813 00000B29 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1814 00000B2A D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1815 00000B2C F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1816 00000B2D D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1817 00000B2F FA                      	cli		; DISABLE INTERRUPTS
  1818 00000B30 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1819 00000B32 90                      	nop		; I/O DELAY
  1820 00000B33 E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1821                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1822                                  	; 24/12/2021
  1823 00000B35 50                      	push	eax
  1824                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1825                                  		     ; ----- 10/06/85 (test4.asm)
  1826 00000B36 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1827                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1828 00000B38 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1829 00000B3A E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1830                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1831                                  	; 24/12/2021
  1832 00000B3C 58                      	pop	eax
  1833 00000B3D 9D                      	popf	
  1834 00000B3E C3                      	retn		; RETURN WITH FLAGS RESTORED
  1835                                  
  1836                                  	; 22/08/2014
  1837                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1838                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1839 00000B3F 51                      	push	ecx
  1840 00000B40 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1841                                  		; mov cx, 800	
  1842                                  UPD_10:
  1843 00000B45 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1844 00000B47 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1845 00000B48 E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1846 00000B4D A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1847 00000B4F 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1848 00000B51 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1849 00000B52 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1850 00000B54 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1851                                  		; xor ax, ax
  1852 00000B56 F9                      	stc				; SET CARRY FOR ERROR
  1853                                  UPD_90:
  1854 00000B57 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1855 00000B58 FA                      	cli				; INTERRUPTS OFF DURING SET
  1856 00000B59 C3                      	retn				; RETURN WITH CY FLAG SET
  1857                                  
  1858                                  bcd_to_ascii:
  1859                                  	; 25/08/2014
  1860                                  	; INPUT ->
  1861                                  	;	al = Packed BCD number
  1862                                  	; OUTPUT ->
  1863                                  	;	ax  = ASCII word/number
  1864                                  	;
  1865                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1866                                  	;
  1867 00000B5A D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1868                                  					; AH = AL / 10h
  1869                                  					; AL = AL MOD 10h
  1870 00000B5C 660D3030                	or ax,'00'                      ; Make it ASCII based
  1871                                  
  1872 00000B60 86E0                            xchg ah, al 
  1873                                  	
  1874 00000B62 C3                      	retn	
  1875                                  	
  1876                                  
  1877                                  %include 'keyboard.inc' ; 07/03/2015
  1878                              <1> ; Retro UNIX 386 v1 Kernel - KEYBOARD.INC
  1879                              <1> ; Last Modification: 23/02/2022
  1880                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1881                              <1> ;
  1882                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1883                              <1> 
  1884                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1885                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1886                              <1> ; 30/06/2015
  1887                              <1> ; 11/03/2015
  1888                              <1> ; 28/02/2015
  1889                              <1> ; 25/02/2015
  1890                              <1> ; 20/02/2015
  1891                              <1> ; 18/02/2015
  1892                              <1> ; 03/12/2014
  1893                              <1> ; 07/09/2014
  1894                              <1> ; KEYBOARD INTERRUPT HANDLER
  1895                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1896                              <1> 
  1897                              <1> ;getch:
  1898                              <1> ;	; 18/02/2015
  1899                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1900                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1901                              <1> ;	; routine, later... (multi tasking ability)
  1902                              <1> ;	; 28/02/2015
  1903                              <1> ;	sti	; enable interrupts
  1904                              <1> ;	;
  1905                              <1> ;	;push	esi
  1906                              <1> ;	;push	ebx
  1907                              <1> ;	;xor	ebx, ebx
  1908                              <1> ;	;mov	bl, [ptty]  ; active_page
  1909                              <1> ;	;mov	esi, ebx
  1910                              <1> ;	;shl 	si, 1
  1911                              <1> ;	;add	esi, ttychr
  1912                              <1> ;getch_1:
  1913                              <1> ;	;mov	ax, [esi]
  1914                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1915                              <1> ;	and	ax, ax
  1916                              <1> ;	jz	short getch_2
  1917                              <1> ;	mov	word [ttychr], 0
  1918                              <1> ;	;mov	word [esi], 0
  1919                              <1> ;	;pop	ebx
  1920                              <1> ;	;pop	esi
  1921                              <1> ;	retn
  1922                              <1> ;getch_2:
  1923                              <1> ;	hlt	; not proper for multi tasking!
  1924                              <1> ;		; (temporary halt for now)
  1925                              <1> ;		; 'sleep' on tty 
  1926                              <1> ;		; will (must) be located here		
  1927                              <1> ;	nop
  1928                              <1> ;	jmp	short getch_1
  1929                              <1> 
  1930                              <1> keyb_int:
  1931                              <1> 	; 23/02/2022
  1932                              <1> 	; 30/06/2015
  1933                              <1> 	; 25/02/2015
  1934                              <1> 	; 20/02/2015
  1935                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1936                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1937                              <1> 	; 30/06/2014
  1938                              <1> 	; 10/05/2013	
  1939                              <1>       	; Retro Unix 8086 v1 feature only!
  1940                              <1> 	; 03/03/2014
  1941                              <1> 	
  1942 00000B63 1E                  <1> 	push	ds
  1943 00000B64 53                  <1> 	push	ebx
  1944 00000B65 50                  <1> 	push	eax
  1945                              <1> 	;
  1946                              <1> 	; 23/02/2022
  1947 00000B66 9C                  <1> 	pushfd
  1948 00000B67 0E                  <1> 	push	cs
  1949                              <1> 	;mov	ax, KDATA
  1950 00000B68 31C0                <1> 	xor	eax, eax
  1951 00000B6A B010                <1> 	mov	al, KDATA
  1952 00000B6C 8ED8                <1> 	mov	ds, ax
  1953                              <1> 	;
  1954                              <1> 	;pushfd
  1955                              <1> 	;push	cs
  1956 00000B6E E810020000          <1> 	call	kb_int   ; int_09h
  1957                              <1> 	;
  1958 00000B73 B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1959                              <1> 	;call	getc
  1960 00000B75 E854000000          <1> 	call	int_16h  ; 30/06/2015
  1961 00000B7A 744E                <1> 	jz	short keyb_int4
  1962                              <1> 	;
  1963 00000B7C B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1964                              <1> 	;call	getc
  1965 00000B7E E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1966                              <1> 	;
  1967                              <1> 	; 20/02/2015
  1968 00000B83 0FB61D[B66B0000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1969                              <1> 	;
  1970 00000B8A 20C0                <1> 	and 	al, al
  1971 00000B8C 751D                <1> 	jnz	short keyb_int1
  1972                              <1> 	;
  1973 00000B8E 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1974 00000B91 7218                <1> 	jb	short keyb_int1
  1975 00000B93 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1976 00000B96 7713                <1> 	ja	short keyb_int1
  1977                              <1> 	;
  1978 00000B98 88D8                <1> 	mov	al, bl
  1979 00000B9A 0468                <1> 	add	al, 68h
  1980 00000B9C 38E0                <1> 	cmp	al, ah
  1981 00000B9E 7409                <1> 	je	short keyb_int0
  1982 00000BA0 88E0                <1> 	mov	al, ah
  1983 00000BA2 2C68                <1> 	sub	al, 68h
  1984 00000BA4 E83F0A0000          <1> 	call	tty_sw
  1985                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1986                              <1> keyb_int0: ; 30/06/2015
  1987                              <1> 	;xor	ax, ax
  1988                              <1> 	; 23/02/2022
  1989 00000BA9 31C0                <1> 	xor	eax, eax
  1990                              <1> keyb_int1:
  1991 00000BAB D0E3                <1> 	shl	bl, 1
  1992 00000BAD 81C3[B86B0000]      <1> 	add	ebx, ttychr
  1993                              <1> 	;
  1994                              <1> 	;23/02/2022
  1995 00000BB3 09C0                <1> 	or	eax, eax
  1996                              <1> 	;or	ax, ax
  1997 00000BB5 7406                <1> 	jz	short keyb_int2
  1998                              <1> 	;
  1999 00000BB7 66833B00            <1> 	cmp 	word [ebx], 0
  2000 00000BBB 7703                <1>         ja      short keyb_int3 
  2001                              <1> keyb_int2:
  2002 00000BBD 668903              <1>         mov	[ebx], ax  ; Save ascii code
  2003                              <1> 			   ; and scan code of the character
  2004                              <1> 			   ; for current tty (or last tty
  2005                              <1> 			   ; just before tty switch).
  2006                              <1> keyb_int3:
  2007 00000BC0 A0[B66B0000]        <1>         mov     al, [ptty]
  2008 00000BC5 E80B440000          <1> 	call	wakeup
  2009                              <1> 	;
  2010                              <1> keyb_int4:
  2011 00000BCA 58                  <1> 	pop	eax
  2012 00000BCB 5B                  <1> 	pop	ebx
  2013 00000BCC 1F                  <1> 	pop	ds
  2014 00000BCD CF                  <1> 	iret
  2015                              <1> 
  2016                              <1> ; 18/02/2015
  2017                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  2018                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  2019                              <1> ; scancode and ascii code of the character 
  2020                              <1> ; in the tty input (ttychr) buffer. 
  2021                              <1> ; Test procedures must call 'getch' for tty input
  2022                              <1> ; otherwise, 'getc' will not be able to return to the caller
  2023                              <1> ; due to infinite (key press) waiting loop.
  2024                              <1> ; 
  2025                              <1> ; 03/12/2014
  2026                              <1> ; 26/08/2014
  2027                              <1> ; KEYBOARD I/O
  2028                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  2029                              <1> 
  2030                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  2031                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  2032                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  2033                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  2034                              <1> 
  2035                              <1> int_16h: ; 30/06/2015
  2036                              <1> ;getc:
  2037 00000BCE 9C                  <1> 	pushfd	; 28/08/2014
  2038 00000BCF 0E                  <1> 	push 	cs
  2039 00000BD0 E826000000          <1> 	call 	getc_int
  2040 00000BD5 C3                  <1> 	retn
  2041                              <1> 
  2042                              <1> ; 24/12/2021
  2043                              <1> 
  2044                              <1> 	;-----	SHIFT STATUS
  2045                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2046 00000BD6 8A25[B4650000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2047 00000BDC 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2048                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2049                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2050 00000BDF C0E405              <1>         shl	ah, 5
  2051 00000BE2 A0[B4650000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2052 00000BE7 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2053 00000BE9 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2054 00000BEB A0[B6650000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2055 00000BF0 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2056 00000BF2 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2057                              <1> _K3:
  2058 00000BF4 A0[B3650000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2059 00000BF9 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2060                              <1> 
  2061                              <1> getc_int:
  2062                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2063                              <1> 	; 28/02/2015
  2064                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2065                              <1> 	;	      instead of pc-at bios - 1985-)
  2066                              <1> 	; 28/08/2014 (_k1d)
  2067                              <1> 	; 30/06/2014
  2068                              <1> 	; 03/03/2014
  2069                              <1> 	; 28/02/2014
  2070                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2071                              <1> 	; rombios source code (21/04/1986)
  2072                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2073                              <1> 	;
  2074                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2075                              <1> 	;
  2076                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2077                              <1> 	; KEYBOARD I/O								      :
  2078                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2079                              <1> 	; INPUT									      :
  2080                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2081                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2082                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2083                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2084                              <1> 	;-----------------------------------------------------------------------------:
  2085                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2086                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2087                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2088                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2089                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2090                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2091                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2092                              <1> 	;-----------------------------------------------------------------------------:	
  2093                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2094                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2095                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2096                              <1> 	;-----------------------------------------------------------------------------:	
  2097                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2098                              <1> 	;	      (AL) = 05H                                                      :
  2099                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2100                              <1> 	;		       							      :
  2101                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2102                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2103                              <1> 	;                     --------------------------------------------            :
  2104                              <1> 	;			00H        30.0        10H        7.5                 :
  2105                              <1> 	;			01H        26.7        11H        6.7                 :
  2106                              <1> 	;			02H        24.0        12H        6.0                 :
  2107                              <1> 	;			03H        21.8        13H        5.5                 :
  2108                              <1> 	;			04H        20.0        14H        5.0                 :
  2109                              <1> 	;			05H        18.5        15H        4.6                 :
  2110                              <1> 	;			06H        17.1        16H        4.3                 :
  2111                              <1> 	;			07H        16.0        17H        4.0                 :
  2112                              <1> 	;			08H        15.0        18H        3.7                 :
  2113                              <1> 	;			09H        13.3        19H        3.3                 :
  2114                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2115                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2116                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2117                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2118                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2119                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2120                              <1> 	;									      :
  2121                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2122                              <1> 	;		       							      :
  2123                              <1> 	;                     REGISTER     DELAY                                      :
  2124                              <1> 	;                      VALUE       VALUE                                      :
  2125                              <1> 	;                     ------------------                                      :
  2126                              <1> 	;			00H        250 ms                                     :
  2127                              <1> 	;			01H        500 ms                                     :
  2128                              <1> 	;			02H        750 ms                                     :
  2129                              <1> 	;			03H       1000 ms                                     :
  2130                              <1> 	;-----------------------------------------------------------------------------:
  2131                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2132                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2133                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2134                              <1> 	;		           (CH) = SCAN CODE                                   :
  2135                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2136                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2137                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2138                              <1> 	;-----------------------------------------------------------------------------:		
  2139                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2140                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2141                              <1> 	;-----------------------------------------------------------------------------:
  2142                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2143                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2144                              <1> 	;-----------------------------------------------------------------------------:	
  2145                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2146                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2147                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2148                              <1> 	; OUTPUT					                              :
  2149                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2150                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2151                              <1> 	;------------------------------------------------------------------------------
  2152                              <1> 	
  2153 00000BFB FB                  <1> 	sti				; INTERRUPTS BACK ON
  2154 00000BFC 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2155 00000BFD 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2156                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2157 00000BFE 66BB1000            <1>         mov     bx, KDATA 
  2158 00000C02 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2159 00000C04 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2160 00000C06 742D                <1> 	jz	short _K1		; ASCII_READ
  2161 00000C08 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2162 00000C0A 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2163 00000C0C FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2164 00000C0E 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2165 00000C10 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2166 00000C12 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2167 00000C14 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2168 00000C17 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2169                              <1> _KIO1:	
  2170 00000C19 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2171 00000C1C 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2172 00000C1E FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2173 00000C20 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2174 00000C22 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2175 00000C24 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2176                              <1> _KIO_EXIT:
  2177                              <1> 	;pop	ecx			; RECOVER REGISTER
  2178 00000C26 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2179 00000C27 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2180 00000C28 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2181                              <1> 
  2182                              <1> 	;-----	ASCII CHARACTER
  2183                              <1> _K1E:	
  2184 00000C29 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2185 00000C2E E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2186 00000C33 EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2187                              <1> _K1:	
  2188 00000C35 E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2189 00000C3A E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2190 00000C3F 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2191                              <1> _K1A:
  2192 00000C41 EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2193                              <1> 
  2194                              <1> 	;-----	ASCII STATUS
  2195                              <1> _K2E:	
  2196 00000C43 E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2197 00000C48 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2198 00000C4A 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2199 00000C4B E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2200 00000C50 EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2201                              <1> _K2:	
  2202 00000C52 E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2203 00000C57 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2204 00000C59 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2205 00000C5A E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2206 00000C5F 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2207 00000C61 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2208 00000C62 E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2209 00000C67 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2210                              <1> _K2A:
  2211 00000C69 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2212                              <1> _K2B:
  2213                              <1> 	;pop	ecx			; RECOVER REGISTER
  2214 00000C6A 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2215 00000C6B 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2216 00000C6C CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2217                              <1> 
  2218                              <1> ; 24/12/2021
  2219                              <1> ;	;-----	SHIFT STATUS
  2220                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2221                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2222                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2223                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2224                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2225                              <1> ;       shl	ah, 5
  2226                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2227                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2228                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2229                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2230                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2231                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2232                              <1> ;_K3:
  2233                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2234                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2235                              <1> 
  2236                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2237                              <1> _K300:
  2238 00000C6F 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2239 00000C71 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2240 00000C73 F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2241 00000C76 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2242 00000C78 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2243 00000C7B 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2244 00000C7D B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2245 00000C7F E880060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2246                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2247                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2248 00000C84 C0E705              <1> 	shl	bh, 5
  2249 00000C87 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2250 00000C89 08F8                <1> 	or	al, bh			; AND DELAY
  2251 00000C8B E874060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2252 00000C90 EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2253                              <1> 
  2254                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2255                              <1> _K500:
  2256 00000C92 56                  <1> 	push	esi			; SAVE SI (esi)
  2257 00000C93 FA                  <1> 	cli				; 
  2258 00000C94 8B1D[C4650000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2259 00000C9A 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2260 00000C9C E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2261 00000CA1 3B1D[C0650000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2262 00000CA7 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2263 00000CA9 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2264 00000CAC 891D[C4650000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2265 00000CB2 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2266 00000CB4 EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2267                              <1> _K502:
  2268 00000CB6 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2269                              <1> _K504:
  2270 00000CB8 FB                  <1> 	sti				
  2271 00000CB9 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2272 00000CBA E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2273                              <1> 
  2274                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2275                              <1> _K1S:
  2276 00000CBF FA                  <1> 	cli	; 03/12/2014
  2277 00000CC0 8B1D[C0650000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2278 00000CC6 3B1D[C4650000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2279                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2280 00000CCC 750F                <1> 	jne	short _k1x ; 03/12/2014
  2281                              <1> 	;
  2282                              <1> 	; 03/12/2014
  2283                              <1> 	; 28/08/2014
  2284                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2285                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2286                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2287                              <1> _K1T:                                   ; ASCII READ
  2288 00000CCE FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2289 00000CCF 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2290                              <1> _K1U:	
  2291 00000CD0 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2292 00000CD1 8B1D[C0650000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2293 00000CD7 3B1D[C4650000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2294                              <1> _k1x:
  2295 00000CDD 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2296 00000CDE 9C                  <1> 	pushf				; SAVE FLAGS
  2297 00000CDF E8D4060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2298 00000CE4 8A1D[B5650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2299 00000CEA 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2300 00000CEC 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2301 00000CEF 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2302 00000CF1 E86E060000          <1> 	call	SND_LED1
  2303 00000CF6 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2304                              <1> _K1V:
  2305 00000CF7 9D                  <1> 	popf				; RESTORE FLAGS
  2306 00000CF8 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2307 00000CF9 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2308                              <1> 	;
  2309 00000CFB 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2310 00000CFE E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2311 00000D03 891D[C0650000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2312 00000D09 C3                  <1> 	retn				; RETURN
  2313                              <1> 
  2314                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2315                              <1> _K2S:
  2316 00000D0A FA                  <1> 	cli				; INTERRUPTS OFF
  2317 00000D0B 8B1D[C0650000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2318 00000D11 3B1D[C4650000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2319 00000D17 668B03              <1> 	mov	ax, [ebx]
  2320 00000D1A 9C                  <1> 	pushf				; SAVE FLAGS
  2321                              <1> 	;push	ax			; SAVE CODE
  2322                              <1> 	; 24/12/2021
  2323 00000D1B 50                  <1> 	push	eax
  2324 00000D1C E897060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2325 00000D21 8A1D[B5650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2326 00000D27 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2327 00000D29 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2328 00000D2C 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2329 00000D2E E81A060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2330                              <1> _K2T:
  2331                              <1> 	;pop	ax			; RESTORE CODE
  2332                              <1> 	; 24/12/2021
  2333 00000D33 58                  <1> 	pop	eax
  2334 00000D34 9D                  <1> 	popf				; RESTORE FLAGS
  2335 00000D35 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2336 00000D36 C3                  <1> 	retn				; RETURN
  2337                              <1> 
  2338                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2339                              <1> _KIO_E_XLAT:
  2340 00000D37 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2341 00000D39 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2342 00000D3B 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2343 00000D3D 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2344 00000D3F 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2345                              <1> _KIO_E_RET:				
  2346 00000D41 C3                  <1> 	retn				; GO BACK
  2347                              <1> 
  2348                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2349                              <1> _KIO_S_XLAT:
  2350 00000D42 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2351 00000D45 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2352 00000D47 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2353 00000D49 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2354 00000D4B 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2355 00000D4D 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2356 00000D4F B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2357                              <1> _kio_ret: ; 03/12/2014
  2358 00000D51 F8                  <1> 	clc
  2359 00000D52 C3                  <1> 	retn
  2360                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2361                              <1> _KIO_S1:				
  2362 00000D53 B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2363                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2364 00000D55 C3                  <1> 	retn
  2365                              <1> _KIO_S2:		
  2366 00000D56 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2367 00000D59 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2368 00000D5B 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2369 00000D5D 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2370 00000D5F 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2371 00000D61 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2372 00000D63 EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2373                              <1> _KIO_S3:
  2374 00000D65 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2375                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2376 00000D67 75E8                <1> 	jne	short _kio_ret
  2377 00000D69 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2378 00000D6B 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2379 00000D6D 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2380                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2381                              <1> _KIO_USE:
  2382                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2383 00000D6F C3                  <1> 	retn				; RETURN	
  2384                              <1> _KIO_DIS:
  2385 00000D70 F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2386 00000D71 C3                  <1> 	retn				; RETURN
  2387                              <1> 
  2388                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2389                              <1> _K4:    
  2390 00000D72 43                  <1> 	inc     ebx
  2391 00000D73 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2392 00000D74 3B1D[BC650000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2393                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2394 00000D7A 7206                <1> 	jb	short _K5
  2395 00000D7C 8B1D[B8650000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2396                              <1> _K5:
  2397 00000D82 C3                  <1> 	retn
  2398                              <1> 
  2399                              <1> ; 20/02/2015
  2400                              <1> ; 05/12/2014
  2401                              <1> ; 26/08/2014
  2402                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2403                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2404                              <1> ;
  2405                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2406                              <1> ; rombios source code (06/10/1985)
  2407                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2408                              <1> 
  2409                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2410                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2411                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2412                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2413                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2414                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2415                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2416                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2417                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2418                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2419                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2420                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2421                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2422                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2423                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2424                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2425                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2426                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2427                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2428                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2429                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2430                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2431                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2432                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2433                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2434                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2435                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2436                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2437                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2438                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2439                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2440                              <1> F11_M		equ	87		; F11 KEY MAKE
  2441                              <1> F12_M		equ	88		; F12 KEY MAKE
  2442                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2443                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2444                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2445                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2446                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2447                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2448                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2449                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2450                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2451                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2452                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2453                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2454                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2455                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2456                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2457                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2458                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2459                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2460                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2461                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2462                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2463                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2464                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2465                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2466                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2467                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2468                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2469                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2470                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2471                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2472                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2473                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2474                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2475                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2476                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2477                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2478                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2479                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2480                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2481                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2482                              <1> ;
  2483                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2484                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2485                              <1> INTA00		equ	020h		; 8259 PORT
  2486                              <1> 
  2487                              <1> 
  2488                              <1> kb_int:
  2489                              <1> 
  2490                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2491                              <1> ; 17/10/2015 ('ctrlbrk') 
  2492                              <1> ; 05/12/2014
  2493                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2494                              <1> 	;	      instead of pc-at bios - 1985-)
  2495                              <1> ; 26/08/2014
  2496                              <1> ;
  2497                              <1> ; 03/06/86  KEYBOARD BIOS
  2498                              <1> ;
  2499                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2500                              <1> ;										;
  2501                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2502                              <1> ;										;
  2503                              <1> ;--------------------------------------------------------------------------------
  2504                              <1> 
  2505                              <1> KB_INT_1:
  2506 00000D83 FB                  <1> 	sti				; ENABLE INTERRUPTS
  2507                              <1> 	;push	ebp
  2508 00000D84 50                  <1> 	push	eax
  2509 00000D85 53                  <1> 	push	ebx
  2510 00000D86 51                  <1> 	push	ecx
  2511 00000D87 52                  <1> 	push	edx
  2512 00000D88 56                  <1> 	push	esi
  2513 00000D89 57                  <1> 	push	edi
  2514 00000D8A 1E                  <1> 	push	ds
  2515 00000D8B 06                  <1> 	push	es
  2516 00000D8C FC                  <1> 	cld				; FORWARD DIRECTION
  2517 00000D8D 66B81000            <1> 	mov	ax, KDATA
  2518 00000D91 8ED8                <1> 	mov	ds, ax
  2519 00000D93 8EC0                <1> 	mov	es, ax
  2520                              <1> 	;
  2521                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2522 00000D95 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2523 00000D97 E856050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2524 00000D9C FA                  <1> 	cli				; DISABLE INTERRUPTS
  2525 00000D9D B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2526                              <1> KB_INT_01:
  2527 00000DA2 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2528 00000DA4 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2529 00000DA6 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2530                              <1> 	;
  2531                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2532 00000DA8 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2533                              <1> 	;
  2534                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2535                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2536                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2537                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2538                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2539                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2540                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2541                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2542                              <1> 	;
  2543                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2544                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2545 00000DAA FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2546 00000DAB 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2547 00000DAD 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2548                              <1> 	;
  2549                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2550 00000DAF 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2551 00000DB1 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2552                              <1> 	;
  2553                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2554 00000DB3 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2555 00000DB4 800D[B5650000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2556 00000DBB E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2557                              <1> 	;
  2558                              <1> 	;-----	RESEND THE LAST BYTE
  2559                              <1> KB_INT_4:
  2560 00000DC0 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2561 00000DC1 800D[B5650000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2562 00000DC8 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2563                              <1> 	;
  2564                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2565                              <1> KB_INT_2:
  2566                              <1> 	;push 	ax			; SAVE DATA IN
  2567                              <1> 	; 24/12/2021
  2568 00000DCD 50                  <1> 	push	eax
  2569 00000DCE E8E5050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2570 00000DD3 8A1D[B5650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2571 00000DD9 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2572 00000DDB 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2573 00000DDE 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2574 00000DE0 E868050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2575                              <1> UP0:
  2576                              <1> 	;pop	ax			; RESTORE DATA IN
  2577                              <1> 	; 24/12/2021
  2578 00000DE5 58                  <1> 	pop	eax
  2579                              <1> ;------------------------------------------------------------------------
  2580                              <1> ;	START OF KEY PROCESSING						;
  2581                              <1> ;------------------------------------------------------------------------
  2582 00000DE6 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2583                              <1> 	;
  2584                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2585 00000DE8 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2586                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2587                              <1> 	; 24/12/2021
  2588 00000DEA 7505                <1> 	jne	short K16
  2589 00000DEC E9ED040000          <1> 	jmp	K62
  2590                              <1> K16:	
  2591 00000DF1 8A3D[B6650000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2592                              <1> 	;
  2593                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2594 00000DF7 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2595 00000DFA 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2596 00000DFC 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2597 00000DFE 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2598 00000E00 7507                <1> 	jne	short RST_RD_ID
  2599 00000E02 800D[B6650000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2600                              <1> RST_RD_ID:
  2601 00000E09 8025[B6650000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2602 00000E10 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2603                              <1> 	; 24/12/2021
  2604                              <1> 	;jmp	K26
  2605                              <1> 	;
  2606                              <1> TST_ID_2:
  2607 00000E12 8025[B6650000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2608 00000E19 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2609 00000E1B 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2610 00000E1D 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2611 00000E1F 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2612                              <1> 	; 24/12/2021
  2613                              <1> 	;jne	K26
  2614                              <1> 	;
  2615                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2616 00000E21 F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2617 00000E24 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2618 00000E26 800D[B3650000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2619 00000E2D E81B050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2620                              <1> KX_BIT:
  2621 00000E32 800D[B6650000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2622 00000E39 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2623                              <1> 	;
  2624                              <1> NOT_ID:
  2625 00000E3E 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2626 00000E40 750E                <1> 	jne	short TEST_E1
  2627 00000E42 800D[B6650000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2628 00000E49 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2629                              <1> 	; 24/12/2021
  2630 00000E4B E9DA010000          <1> 	jmp	K26A	
  2631                              <1> TEST_E1:	
  2632 00000E50 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2633 00000E52 750C                <1> 	jne	short NOT_HC
  2634 00000E54 800D[B6650000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2635 00000E5B E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2636                              <1> 	;
  2637                              <1> NOT_HC:
  2638 00000E60 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2639 00000E62 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2640 00000E65 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2641                              <1> 	;
  2642 00000E67 BF[9E640000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2643 00000E6C AE                  <1> 	scasb
  2644                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2645                              <1> 	; 24/12/2021
  2646 00000E6D 7458                <1> 	je	short K16B
  2647 00000E6F AE                  <1> 	scasb
  2648 00000E70 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2649 00000E72 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2650                              <1> 	; 24/12/2021
  2651                              <1> 	;jmp	K26
  2652                              <1> 	;
  2653                              <1> NOT_LC_E0:
  2654 00000E74 F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2655 00000E77 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2656 00000E79 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2657 00000E7E BF[9C640000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2658 00000E83 F2AE                <1> 	repne	scasb			; CHECK IT
  2659 00000E85 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2660                              <1> 	; 24/12/2021
  2661                              <1> 	;je	K26A			
  2662                              <1> 	;
  2663 00000E87 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2664 00000E89 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2665                              <1> 	; 24/12/2021
  2666                              <1> 	;jne	K26
  2667 00000E8B F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2668 00000E8E 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2669                              <1> 	; 24/12/2021
  2670                              <1> 	;jnz	K26
  2671                              <1>         ; 20/02/2015 
  2672 00000E90 F605[B4650000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2673 00000E97 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2674                              <1> 	; 24/12/2021
  2675                              <1> 	;jnz	K26
  2676 00000E99 E9D6020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2677                              <1> 	;
  2678                              <1> 	;-----	TEST FOR SYSTEM KEY
  2679                              <1> T_SYS_KEY:
  2680 00000E9E 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2681 00000EA0 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2682                              <1> 	;
  2683 00000EA2 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2684 00000EA5 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2685                              <1> 	;
  2686 00000EA7 F605[B4650000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2687 00000EAE 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2688                              <1> 	;jnz	K26			
  2689                              <1> 	;
  2690 00000EB0 800D[B4650000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2691 00000EB7 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2692 00000EB9 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2693                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2694 00000EBB B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2695 00000EBD E830040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2696                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2697                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2698                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2699                              <1> 	;INT	15H			; USER INTERRUPT	
  2700 00000EC2 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2701                              <1> 	;
  2702 00000EC7 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2703                              <1> 	;
  2704                              <1> K16C:
  2705 00000ECC 8025[B4650000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2706 00000ED3 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2707 00000ED5 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2708                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2709                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2710                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2711                              <1> 	;
  2712                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2713                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2714                              <1> 	;INT	15H			; USER INTERRUPT
  2715                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2716                              <1> 	;
  2717 00000ED7 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2718                              <1> 	;
  2719                              <1> 	;-----	TEST FOR SHIFT KEYS
  2720                              <1> K16A:
  2721 00000EDC 8A1D[B3650000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2722 00000EE2 BF[98640000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2723 00000EE7 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2724 00000EEC F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2725 00000EEE 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2726                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2727                              <1> 	; 24/12/2021
  2728 00000EF0 7405                <1> 	je	short K17
  2729 00000EF2 E914010000          <1> 	jmp	K25
  2730                              <1> 	;
  2731                              <1> 	;------	SHIFT KEY FOUND
  2732                              <1> K17:
  2733 00000EF7 81EF[99640000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2734 00000EFD 8AA7[A0640000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2735 00000F03 B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2736 00000F05 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2737                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2738                              <1> 	; 24/12/2021
  2739 00000F07 7405                <1> 	jz	short K17C
  2740 00000F09 E999000000          <1> 	jmp	K23
  2741                              <1> 	;
  2742                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2743                              <1> K17C:
  2744 00000F0E 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2745 00000F11 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2746                              <1> 	;
  2747                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2748 00000F13 0825[B3650000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2749 00000F19 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2750 00000F1B 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2751                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2752                              <1> 	; 24/12/2021
  2753 00000F1D E901010000          <1> 	jmp	K26
  2754                              <1> K17D:
  2755 00000F22 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2756 00000F25 740B                <1> 	jz 	short K17E		; NO, JUMP
  2757 00000F27 0825[B6650000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2758 00000F2D E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2759                              <1> K17E:
  2760 00000F32 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2761 00000F34 0825[B4650000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2762 00000F3A E9E4000000          <1> 	jmp	K26
  2763                              <1> 	;
  2764                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2765                              <1> K18:					; SHIFT-TOGGLE
  2766 00000F3F F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2767 00000F42 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2768                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2769                              <1> 	; 24/12/2021
  2770 00000F44 E9C2000000          <1> 	jmp	K25
  2771                              <1> K18A:
  2772 00000F49 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2773 00000F4B 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2774 00000F4D F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2775 00000F50 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2776                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2777                              <1> 	; 24/12/2021
  2778 00000F52 E9B4000000          <1> 	jmp	K25
  2779                              <1> K18B:
  2780 00000F57 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2781 00000F5A 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2782                              <1> K19:	
  2783 00000F5C F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2784 00000F5F 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2785 00000F61 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2786 00000F64 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2787                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2788 00000F66 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2789 00000F68 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2790                              <1> K21:					; MIGHT BE NUMERIC
  2791 00000F6D F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2792 00000F70 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2793                              <1> 	;
  2794                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2795 00000F72 8425[B4650000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2796                              <1> 	;jnz	K26
  2797                              <1> 	; 24/12/2021
  2798 00000F78 7405                <1> 	jz	short K22A
  2799 00000F7A E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2800                              <1> K22A:
  2801 00000F7F 0825[B4650000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2802 00000F85 3025[B3650000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2803                              <1> 	;
  2804                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2805 00000F8B F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2806 00000F8E 7407                <1> 	jz	short K22B		; GO IF NOT
  2807                              <1> 	;
  2808                              <1> 	; 24/12/2021
  2809                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2810 00000F90 50                  <1> 	push	eax
  2811 00000F91 E8B7030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2812                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2813 00000F96 58                  <1> 	pop	eax
  2814                              <1> K22B:
  2815 00000F97 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2816                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2817                              <1> 	; 24/12/2021
  2818 00000F99 7405                <1> 	je	short K22C
  2819 00000F9B E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2820                              <1> K22C:
  2821 00000FA0 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2822 00000FA2 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2823                              <1> 	;
  2824                              <1> 	;-----	BREAK SHIFT FOUND
  2825                              <1> K23:					; BREAK-SHIFT-FOUND
  2826 00000FA7 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2827 00000FAA F6D4                <1> 	not	ah			; INVERT MASK
  2828 00000FAC 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2829 00000FAE 2025[B3650000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2830 00000FB4 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2831 00000FB7 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2832                              <1> 	;
  2833 00000FB9 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2834 00000FBC 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2835 00000FBE 2025[B6650000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2836 00000FC4 EB08                <1> 	jmp	short K23B		; CONTINUE
  2837                              <1> K23A:
  2838 00000FC6 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2839 00000FC8 2025[B4650000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2840                              <1> K23B:
  2841 00000FCE 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2842 00000FD0 A0[B6650000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2843 00000FD5 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2844 00000FD7 0A05[B4650000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2845 00000FDD D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2846 00000FDF 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2847 00000FE1 0805[B3650000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2848 00000FE7 88E0                <1> 	mov	al, ah
  2849                              <1> K23D:
  2850 00000FE9 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2851 00000FEB 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2852                              <1> 	;	
  2853                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2854 00000FED A0[B7650000]        <1> 	mov	al, [ALT_INPUT]
  2855 00000FF2 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2856 00000FF4 8825[B7650000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2857 00000FFA 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2858 00000FFC 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2859 00000FFE E9B8020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2860                              <1> 	;
  2861                              <1> K24:					; BREAK-TOGGLE
  2862 00001003 2025[B4650000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2863 00001009 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2864                              <1> 	;
  2865                              <1> 	;-----	TEST FOR HOLD STATE
  2866                              <1> 					; AL, AH = SCAN CODE
  2867                              <1> K25:					; NO-SHIFT-FOUND
  2868 0000100B 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2869 0000100D 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2870 0000100F F605[B4650000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2871 00001016 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2872 00001018 3C45                <1> 	cmp	al, NUM_KEY
  2873 0000101A 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2874 0000101C 8025[B4650000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2875                              <1> 	;
  2876                              <1> K26:
  2877 00001023 8025[B6650000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2878                              <1> K26A:					; INTERRUPT-RETURN
  2879 0000102A FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2880 0000102B B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2881 0000102D E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2882                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2883 0000102F B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2884 00001031 E8BC020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2885                              <1> K27A:
  2886 00001036 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2887 00001037 07                  <1> 	pop	es			; RESTORE REGISTERS
  2888 00001038 1F                  <1> 	pop	ds
  2889 00001039 5F                  <1> 	pop	edi
  2890 0000103A 5E                  <1> 	pop	esi
  2891 0000103B 5A                  <1> 	pop	edx
  2892 0000103C 59                  <1> 	pop	ecx
  2893 0000103D 5B                  <1> 	pop	ebx
  2894 0000103E 58                  <1> 	pop	eax
  2895                              <1> 	;pop	ebp
  2896 0000103F CF                  <1> 	iret				; RETURN
  2897                              <1> 
  2898                              <1> 	;-----	NOT IN	HOLD STATE
  2899                              <1> K28:					; NO-HOLD-STATE
  2900 00001040 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2901 00001042 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2902                              <1> 	;
  2903 00001044 F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2904 00001047 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2905                              <1>         ; 24/12/2021
  2906                              <1> 	;jz      K38
  2907                              <1> 	;
  2908 00001049 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2909 0000104C 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2910                              <1> 	; 28/02/2015
  2911 0000104E F605[B4650000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2912 00001055 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2913                              <1> 	; 24/12/2021
  2914                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2915                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2916 00001057 E9D1000000          <1> K28A:	jmp	K38
  2917                              <1> 	;
  2918                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2919                              <1> K29:					; TEST-RESET
  2920 0000105C F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2921 0000105F 740B                <1> 	jz	short K31		; NO_RESET
  2922 00001061 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2923 00001063 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2924                              <1> 	;
  2925                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2926                              <1>  	; 26/08/2014
  2927                              <1> cpu_reset:
  2928                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2929                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2930 00001065 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2931 00001067 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2932                              <1> khere:
  2933 00001069 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2934 0000106A EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2935                              <1> 
  2936                              <1> 	;
  2937                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2938                              <1> K31:					; NO-RESET
  2939 0000106C 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2940 0000106E 7507                <1> 	jne	short K311		; NOT THERE
  2941 00001070 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2942 00001072 E936020000          <1>         jmp     K57                     ; BUFFER_FILL
  2943                              <1> K311:
  2944 00001077 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2945 00001079 7509                <1> 	jne	short K312		; NOT THERE
  2946 0000107B 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2947 0000107F E929020000          <1>         jmp     K57                     ; BUFFER_FILL
  2948                              <1> K312:
  2949 00001084 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2950 00001086 7471                <1>         je	short K37B              ; GO PROCESS
  2951 00001088 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2952 0000108A 746D                <1>         je	short K37B              ; GO PROCESS
  2953                              <1> 	;
  2954                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2955                              <1> K32:					; ALT-KEY-PAD
  2956 0000108C BF[74640000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2957 00001091 B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2958 00001096 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2959 00001098 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2960 0000109A F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2961                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2962                              <1> 	; 24/12/2021
  2963 0000109D 751C                <1> 	jnz	short K32B
  2964 0000109F 81EF[75640000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2965 000010A5 A0[B7650000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2966 000010AA B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2967 000010AC F6E4                <1> 	mul	ah
  2968 000010AE 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2969 000010B1 A2[B7650000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2970                              <1> K32A:
  2971 000010B6 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2972                              <1> K32B:
  2973                              <1> 	; 24/12/2021
  2974 000010BB EB6A                <1> 	jmp	K37C
  2975                              <1> 	;
  2976                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2977                              <1> K33:					; NO-ALT-KEYPAD
  2978 000010BD C605[B7650000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2979 000010C4 B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2980 000010C9 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2981 000010CB 7453                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2982                              <1> 	;
  2983                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2984                              <1> K34:					; ALT-TOP-ROW
  2985 000010CD 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2986 000010CF 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2987 000010D1 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2988 000010D3 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2989 000010D5 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2990 000010D8 EB46                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2991                              <1> 	;
  2992                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2993                              <1> K35:					; ALT-FUNCTION
  2994 000010DA 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2995 000010DC 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2996 000010DE 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2997 000010E0 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2998 000010E2 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2999 000010E5 EB39                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  3000                              <1> K35A:
  3001 000010E7 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  3002 000010EA 7425                <1> 	jz	short K37		; NO, JUMP
  3003 000010EC 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  3004 000010EE 7510                <1>         jne     short K35B              ; NOT THERE
  3005 000010F0 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  3006 000010F4 E9B4010000          <1> 	jmp	K57			; BUFFER FILL
  3007                              <1> K37B:
  3008 000010F9 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  3009 000010FB E9AD010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  3010                              <1> K35B:
  3011 00001100 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  3012 00001102 7423                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  3013 00001104 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  3014 00001106 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  3015                              <1>         ; 24/12/2021
  3016                              <1> 	;jne	K26
  3017 00001108 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  3018 0000110C E99C010000          <1> 	jmp	K57			; BUFFER FILL
  3019                              <1> K37:
  3020 00001111 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  3021 00001113 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  3022 00001115 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  3023                              <1>         ;ja	short K32A		; IF SO, IGNORE
  3024 00001117 0F8706FFFFFF        <1>         ja      K26
  3025 0000111D 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  3026                              <1> K37A:
  3027 00001120 B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  3028 00001122 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  3029                              <1> K37C:
  3030 00001127 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  3031 00001129 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  3032 0000112B EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  3033                              <1> 	;
  3034                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  3035                              <1> K38:					; NOT-ALT-SHIFT
  3036                              <1> 					; BL STILL HAS SHIFT FLAGS
  3037 0000112D F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  3038 00001130 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  3039                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  3040                              <1> 	; 24/12/2021
  3041 00001132 E9AB000000          <1> 	jmp	K44
  3042                              <1> 	;
  3043                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3044                              <1> 	;-----	TEST FOR BREAK
  3045                              <1> K38A:
  3046 00001137 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3047 00001139 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3048 0000113B F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3049 0000113E 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3050 00001140 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3051 00001143 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3052                              <1> K38B:
  3053 00001145 8B1D[C0650000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3054 0000114B 891D[C4650000]      <1> 	mov	[BUFFER_TAIL], ebx
  3055 00001151 C605[B2650000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3056                              <1> 	;
  3057                              <1> 	;-----	ENABLE KEYBOARD
  3058 00001158 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3059 0000115A E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3060                              <1> 	;
  3061                              <1> 	; CTRL+BREAK code here !!!
  3062                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3063                              <1> 	; 17/10/2015	
  3064 0000115F E85C220000          <1> 	call	ctrlbrk ; control+break subroutine
  3065                              <1> 	;
  3066                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3067                              <1> 	; 24/12/2021
  3068 00001164 29C0                <1> 	sub	eax, eax
  3069 00001166 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3070                              <1> 	;
  3071                              <1> 	;-----	TEST FOR PAUSE
  3072                              <1> K39:					; NO_BREAK
  3073 0000116B F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3074 0000116E 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3075 00001170 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3076 00001172 7533                <1> 	jne	short K41		; NO-PAUSE
  3077                              <1> K39P:
  3078 00001174 800D[B4650000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3079                              <1> 	;
  3080                              <1> 	;-----	ENABLE KEYBOARD
  3081 0000117B B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3082 0000117D E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3083                              <1> K39A:
  3084 00001182 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3085 00001184 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3086                              <1> 	;
  3087                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3088 00001186 803D[B0650000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3089 0000118D 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3090 0000118F 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3091 00001193 A0[B1650000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3092 00001198 EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3093                              <1> 	;
  3094                              <1> K40:					; PAUSE-LOOP
  3095 00001199 F605[B4650000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3096 000011A0 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3097                              <1> 	;
  3098 000011A2 E988FEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3099                              <1>         ;
  3100                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3101                              <1> K41:					; NO-PAUSE
  3102 000011A7 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3103 000011A9 7513                <1> 	jne	short K42		; NOT-KEY-55
  3104 000011AB F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3105 000011AE 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3106 000011B0 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3107 000011B3 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3108                              <1> K41A:	
  3109 000011B5 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3110 000011B9 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3111                              <1> 	;
  3112                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3113                              <1> K42:					; NOT-KEY-55
  3114 000011BE 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3115 000011C0 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3116 000011C2 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3117 000011C4 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3118 000011C6 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3119 000011C9 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3120 000011CB 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3121 000011CF E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3122                              <1> K42A:
  3123                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3124 000011D4 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3125                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3126                              <1> 	;;jb	K56 ; 20/02/2015
  3127                              <1> 	;;jmp	K64 ; 20/02/2015
  3128                              <1> K42B:
  3129 000011D6 BB[A8640000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3130                              <1> 	;;jmp	K64
  3131                              <1> 	;jb	K56 ;; 20/02/2015	
  3132                              <1> 	; 24/12/2021
  3133 000011DB 7267                <1> 	jb	short K45F
  3134 000011DD E9B9000000          <1> 	jmp	K64	
  3135                              <1>         ;
  3136                              <1> 	;-----	NOT IN CONTROL SHIFT
  3137                              <1> K44:					; NOT-CTL-SHIFT
  3138 000011E2 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3139 000011E4 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3140 000011E6 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3141 000011E9 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3142 000011EB F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3143 000011EE 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3144 000011F0 EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3145                              <1> K44A:
  3146 000011F2 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3147 000011F5 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3148                              <1> 	;
  3149                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3150                              <1> K44B:
  3151 000011F7 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3152 000011F9 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3153 000011FE B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3154 00001200 E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3155                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3156                              <1> 	;PUSH 	BP			; SAVE POINTER
  3157                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3158                              <1> 	;POP	BP			; RESTORE POINTER
  3159 00001202 8025[B6650000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3160 00001209 E921FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3161                              <1> 	;
  3162                              <1> 	;-----	HANDLE IN-CORE KEYS
  3163                              <1> K45:					; NOT-PRINT-SCREEN
  3164 0000120E 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3165 00001210 7734                <1> 	ja	short K46		; JUMP IF NOT
  3166 00001212 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3167 00001214 7505                <1> 	jne	short K45A		; NO, JUMP
  3168 00001216 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3169 00001219 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3170                              <1> K45A:
  3171 0000121B B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3172 00001220 BF[7E640000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3173 00001225 F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3174                              <1> 		; 20/02/2015
  3175 00001227 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3176                              <1> 	;
  3177 00001229 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3178 0000122C 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3179                              <1> K45B:
  3180 0000122E F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3181 00001231 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3182                              <1> 					; NO, LOWERCASE
  3183                              <1> K45C:
  3184 00001233 BB[00650000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3185 00001238 EB51                <1> 	jmp	short K56	
  3186                              <1> K45D:					; ALMOST-CAPS-STATE
  3187 0000123A F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3188 0000123D 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3189                              <1> K45E:
  3190 0000123F BB[58650000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3191 00001244 EB45                <1> K45F:	jmp	short K56
  3192                              <1> 	;
  3193                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3194                              <1> K46:					; NOT IN-CORE AREA
  3195 00001246 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3196                              <1> 	;ja	short K47		; JUMP IF NOT
  3197                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3198 00001248 7635                <1> 	jna	short K53		
  3199                              <1> 	;
  3200                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3201                              <1> K47:					; NOT F1 - F10
  3202 0000124A 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3203 0000124C 772D                <1> 	ja	short K52		; JUMP IF NOT
  3204                              <1> 	;
  3205                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3206                              <1> K48:
  3207 0000124E 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3208 00001250 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3209 00001252 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3210 00001254 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3211 00001256 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3212 00001259 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3213                              <1> 	;		
  3214 0000125B F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3215 0000125E 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3216 00001260 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3217                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3218 00001263 75DA                <1> 	jnz	short K45E
  3219                              <1> 	;
  3220                              <1> 	;-----	BASE CASE FOR KEYPAD
  3221                              <1> K49:					
  3222 00001265 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3223 00001267 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3224 00001269 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3225 0000126B EB40                <1> 	jmp	short K57		; BUFFER FILL
  3226                              <1> K49A:
  3227 0000126D BB[00650000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3228 00001272 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3229                              <1> 	;
  3230                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3231                              <1> K50:					; ALMOST-NUM-STATE
  3232 00001274 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3233 00001277 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3234 00001279 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3235                              <1> 	;
  3236                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3237                              <1> K52:					; NOT A NUMPAD KEY
  3238 0000127B 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3239                              <1> 	;jne	short K53		; JUMP IF NOT
  3240                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3241 0000127D 74AF                <1> 	je	short K45B		
  3242                              <1> 	;
  3243                              <1> 	;-----	MUST BE F11 OR F12 
  3244                              <1> K53:					; F1 - F10 COME HERE, TOO
  3245 0000127F F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3246 00001282 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3247                              <1> 		; 20/02/2015 
  3248 00001284 BB[58650000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3249 00001289 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3250                              <1> 	;
  3251                              <1> 	;-----	TRANSLATE THE CHARACTER
  3252                              <1> K56:					; TRANSLATE-CHAR
  3253 0000128B FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3254 0000128D D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3255 0000128E F605[B6650000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3256 00001295 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3257 00001297 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3258 00001299 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3259                              <1> 	;
  3260                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3261                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3262 0000129B FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3263 0000129D D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3264 0000129E 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3265 000012A0 B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3266 000012A2 F605[B6650000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3267 000012A9 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3268 000012AB B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3269                              <1> 	;
  3270                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3271                              <1> K57:					; BUFFER_FILL
  3272 000012AD 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3273 000012AF 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3274                              <1> 	; 24/12/2021
  3275                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3276 000012B1 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3277                              <1> 	; 24/12/2021
  3278 000012B4 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3279                              <1> 	;je	K26			; INTERRUPT_RETURN
  3280                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3281 000012B6 E968FDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3282                              <1> K61:					; NOT-CAPS-STATE
  3283 000012BB 8B1D[C4650000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3284 000012C1 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3285 000012C3 E8AAFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3286 000012C8 3B1D[C0650000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3287 000012CE 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3288 000012D0 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3289 000012D3 891D[C4650000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3290 000012D9 E945FDFFFF          <1> 	jmp	K26
  3291                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3292                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3293                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3294                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3295                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3296                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3297                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3298                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3299                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3300                              <1> 	;;jmp   K27                    
  3301                              <1> 	;
  3302                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3303                              <1> K62:
  3304 000012DE B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3305 000012E0 E620                <1> 	out	INTA00, al
  3306 000012E2 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3307 000012E6 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3308 000012E8 E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3309 000012ED E93DFDFFFF          <1> 	jmp     K27			; EXIT   
  3310                              <1> 
  3311                              <1> SHIP_IT:
  3312                              <1> 	;---------------------------------------------------------------------------------
  3313                              <1> 	; SHIP_IT
  3314                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3315                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3316                              <1> 	;---------------------------------------------------------------------------------
  3317                              <1> 	;
  3318                              <1> 	;push	ax			; SAVE DATA TO SEND
  3319                              <1> 	; 24/12/2021
  3320 000012F2 50                  <1> 	push	eax
  3321                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3322 000012F3 FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3323                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3324 000012F4 B900000100          <1> 	mov	ecx, 10000h			
  3325                              <1> S10:
  3326 000012F9 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3327 000012FB A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3328 000012FD E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3329                              <1> 
  3330                              <1> 	;pop	ax			; GET DATA TO SEND
  3331                              <1> 	; 24/12/2021
  3332 000012FF 58                  <1> 	pop	eax
  3333 00001300 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3334 00001302 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3335 00001303 C3                  <1> 	retn				; RETURN TO CALLER
  3336                              <1> 
  3337                              <1> SND_DATA:
  3338                              <1> 	; ---------------------------------------------------------------------------------
  3339                              <1> 	; SND_DATA
  3340                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3341                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3342                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3343                              <1> 	; ---------------------------------------------------------------------------------
  3344                              <1> 	;
  3345                              <1> 	;push	ax			; SAVE REGISTERS
  3346                              <1> 	;push	bx
  3347                              <1> 	; 24/12/2021
  3348 00001304 50                  <1> 	push	eax
  3349 00001305 53                  <1> 	push	ebx
  3350 00001306 51                  <1> 	push	ecx
  3351 00001307 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3352 00001309 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3353                              <1> SD0:
  3354 0000130B FA                  <1> 	cli				; DISABLE INTERRUPTS
  3355 0000130C 8025[B5650000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3356                              <1> 	;
  3357                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3358 00001313 B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3359                              <1> SD5:
  3360 00001318 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3361 0000131A A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3362 0000131C E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3363                              <1> 	;
  3364 0000131E 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3365 00001320 E660                <1> 	out	PORT_A, al		; SEND BYTE
  3366 00001322 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3367                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3368 00001323 B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3369                              <1> SD1:
  3370 00001328 F605[B5650000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3371 0000132F 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3372 00001331 E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3373                              <1> SD2:
  3374 00001333 FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3375 00001335 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3376 00001337 800D[B5650000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3377 0000133E EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3378                              <1> SD3:
  3379 00001340 F605[B5650000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3380 00001347 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3381                              <1> SD4:	
  3382 00001349 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3383                              <1> 	;pop	bx
  3384                              <1> 	;pop	ax
  3385                              <1> 	; 24/12/2021
  3386 0000134A 5B                  <1> 	pop	ebx
  3387 0000134B 58                  <1> 	pop	eax
  3388 0000134C C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3389                              <1> 
  3390                              <1> SND_LED:
  3391                              <1> 	; ---------------------------------------------------------------------------------
  3392                              <1> 	; SND_LED
  3393                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3394                              <1> 	;
  3395                              <1> 	;----------------------------------------------------------------------------------
  3396                              <1> 	;
  3397 0000134D FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3398 0000134E F605[B5650000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3399 00001355 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3400                              <1> 	;
  3401 00001357 800D[B5650000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3402 0000135E B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3403 00001360 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3404 00001362 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3405                              <1> SND_LED1:
  3406 00001364 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3407 00001365 F605[B5650000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3408 0000136C 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3409                              <1> 	;
  3410 0000136E 800D[B5650000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3411                              <1> SL0:
  3412 00001375 B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3413 00001377 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3414 0000137C FA                  <1> 	cli
  3415 0000137D E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3416 00001382 8025[B5650000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3417 00001389 0805[B5650000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3418 0000138F F605[B5650000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3419 00001396 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3420                              <1> 	;
  3421 00001398 E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3422 0000139D FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3423 0000139E F605[B5650000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3424 000013A5 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3425                              <1> SL2:
  3426 000013A7 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3427 000013A9 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3428 000013AE FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3429                              <1> SL3:
  3430 000013AF 8025[B5650000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3431                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3432 000013B6 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3433 000013B7 C3                  <1> 	retn				; RETURN TO CALLER
  3434                              <1> 
  3435                              <1> MAKE_LED:
  3436                              <1> 	;---------------------------------------------------------------------------------
  3437                              <1> 	; MAKE_LED
  3438                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3439                              <1> 	;	THE MODE INDICATORS.
  3440                              <1> 	;---------------------------------------------------------------------------------
  3441                              <1> 	;
  3442                              <1> 	;push 	cx			; SAVE CX
  3443 000013B8 A0[B3650000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3444 000013BD 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3445                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3446                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3447 000013BF C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3448 000013C2 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3449                              <1> 	;pop	cx
  3450 000013C4 C3                  <1> 	retn				; RETURN TO CALLER
  3451                              <1> 
  3452                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3453                              <1> 
  3454                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1878                                  
  1879                                  %include 'video.inc' ; 07/03/2015
  1880                              <1> ; Retro UNIX 386 v1 Kernel - VIDEO.INC
  1881                              <1> ; Last Modification: 26/02/2022
  1882                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1883                              <1> ;
  1884                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1885                              <1> 
  1886                              <1> ; 07/02/2022
  1887                              <1> ; 02/02/2022 (simplified scroll up)
  1888                              <1> ; 16/01/2016
  1889                              <1> ; 30/06/2015
  1890                              <1> ; 27/06/2015
  1891                              <1> ; 11/03/2015
  1892                              <1> ; 02/09/2014
  1893                              <1> ; 30/08/2014
  1894                              <1> ; VIDEO FUNCTIONS
  1895                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1896                              <1> 
  1897                              <1> write_tty:
  1898                              <1> 	; 02/02/2022
  1899                              <1> 	; 13/08/2015
  1900                              <1> 	; 02/09/2014
  1901                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1902                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1903                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1904                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1905                              <1> 	;
  1906                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1907                              <1> 	;	   AL = Character to be written
  1908                              <1> 	;	   EBX = Video Page (0 to 7)
  1909                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1910                              <1> 
  1911                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1912                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1913                              <1> 
  1914                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1915                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1916                              <1> ;
  1917                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1918                              <1> ;
  1919                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1920                              <1> ;										:
  1921                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1922                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1923                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1924                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1925                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1926                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1927                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1928                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1929                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1930                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1931                              <1> ;   THE 0 COLOR IS USED.							:
  1932                              <1> ;   ENTRY --									:
  1933                              <1> ;     (AH) = CURRENT CRT MODE							:
  1934                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1935                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1936                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1937                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1938                              <1> ;   EXIT -- 									:
  1939                              <1> ;     ALL REGISTERS SAVED							:
  1940                              <1> ;--------------------------------------------------------------------------------
  1941                              <1> 
  1942 000013C5 FA                  <1> 	cli
  1943                              <1> 	;
  1944                              <1> 	; READ CURSOR (04/12/2013)
  1945                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1946 000013C6 08FF                <1> 	or	bh, bh
  1947                              <1> 	;jnz	beeper
  1948                              <1> 	; 02/02/2022
  1949 000013C8 7405                <1> 	jz	short u14
  1950 000013CA E992000000          <1> 	jmp	beeper
  1951                              <1> u14:
  1952                              <1> 	; 02/02/2022
  1953                              <1> 	;; 01/09/2014
  1954                              <1> 	;cmp	byte [CRT_MODE], 3
  1955                              <1> 	;je	short m3
  1956                              <1> 	;;
  1957                              <1> 	;call	set_mode
  1958                              <1> m3:
  1959 000013CF 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1960                              <1> 	;shl	si, 1
  1961                              <1> 	; 02/02/2022
  1962 000013D1 D1E6                <1> 	shl	esi, 1
  1963 000013D3 81C6[A66B0000]      <1> 	add	esi, cursor_posn
  1964 000013D9 668B16              <1> 	mov	dx, [esi]
  1965                              <1> 	;
  1966                              <1> 	; dx now has the current cursor position
  1967                              <1> 	;
  1968 000013DC 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1969 000013DE 7647                <1> 	jbe	short u8
  1970                              <1> 	;
  1971                              <1> 	; write the char to the screen
  1972                              <1> u0:	
  1973                              <1> 	; ah = attribute/color
  1974                              <1> 	; al = character
  1975                              <1> 	; bl = video page number (0 to 7)
  1976                              <1> 	; bh = 0
  1977                              <1> 	;
  1978 000013E0 E8D6010000          <1> 	call	write_c_current
  1979                              <1> 	;
  1980                              <1> 	; position the cursor for next char
  1981 000013E5 FEC2                <1> 	inc	dl		; next column
  1982                              <1> 	;cmp	dl, [CRT_COLS]
  1983 000013E7 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1984                              <1>         ;jne	set_cpos
  1985                              <1> 	; 02/02/2022
  1986 000013EA 7405                <1> 	je	short u13
  1987 000013EC E9DE000000          <1> 	jmp	set_cpos
  1988                              <1> u13:
  1989 000013F1 B200                <1> 	mov	dl, 0		; column = 0
  1990                              <1> u10:				; (line feed found)
  1991 000013F3 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1992 000013F6 7228                <1> 	jb 	short u6
  1993                              <1> 	;
  1994                              <1> 	; scroll required
  1995                              <1> u1:	
  1996                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1997 000013F8 E8D2000000          <1> 	call	set_cpos
  1998                              <1> 	;
  1999                              <1> 	; determine value to fill with during scroll
  2000                              <1> u2:
  2001                              <1> 	; READ_AC_CURRENT		:
  2002                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  2003                              <1> 	;    AT THE CURRENT CURSOR POSITION
  2004                              <1> 	;
  2005                              <1> 	; INPUT				
  2006                              <1> 	;	(AH) = CURRENT CRT MODE
  2007                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  2008                              <1> 	;	(DS) = DATA SEGMENT
  2009                              <1> 	;	(ES) = REGEN SEGMENT
  2010                              <1> 	; OUTPUT			
  2011                              <1> 	;	(AL) = CHARACTER READ
  2012                              <1> 	;	(AH) = ATTRIBUTE READ
  2013                              <1> 	;
  2014                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  2015                              <1> 	;
  2016                              <1> 	; bl = video page number
  2017                              <1> 	;
  2018 000013FD E82D010000          <1> 	call	find_position	; get regen location and port address
  2019                              <1> 	; dx = status port
  2020                              <1> 	; esi = cursor location/address
  2021                              <1> p11:
  2022 00001402 FB                  <1> 	sti			; enable interrupts
  2023 00001403 90                  <1> 	nop			; allow for small interupts window
  2024 00001404 FA                  <1> 	cli			; blocks interrupts for single loop
  2025 00001405 EC                  <1> 	in	al, dx		; get status from adapter
  2026 00001406 A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  2027 00001408 75F8                <1> 	jnz	short p11	; wait until it is
  2028                              <1> p12:				; now wait for either retrace high
  2029 0000140A EC                  <1> 	in	al, dx		; get status
  2030 0000140B A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  2031 0000140D 74FB                <1> 	jz	short p12	; wait until either is active	
  2032                              <1> p13:
  2033 0000140F 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2034 00001415 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2035                              <1> 	;
  2036                              <1> 	; al = character, ah = attribute
  2037                              <1> 	;
  2038 00001418 FB                  <1> 	sti
  2039                              <1> 	; bl = video page number 	
  2040                              <1> u3:
  2041                              <1> 	;;mov	ax, 0601h 	; scroll one line
  2042                              <1> 	;;sub	cx, cx		; upper left corner
  2043                              <1> 	;;mov	dh, 25-1 	; lower right row
  2044                              <1> 	;;;mov	dl, [CRT_COLS]
  2045                              <1> 	;mov	dl, 80		; lower right column	
  2046                              <1> 	;;dec	dl
  2047                              <1> 	;;mov	dl, 79
  2048                              <1> 
  2049                              <1> 	;;call	scroll_up	; 04/12/2013
  2050                              <1> 	;;; 11/03/2015
  2051                              <1> 	; 02/09/2014
  2052                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2053                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2054                              <1> 	; 11/03/2015
  2055                              <1> 	;sub	cx, cx
  2056                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2057                              <1> 	;
  2058                              <1> 	; 02/02/2022 (simplied scroll up)
  2059                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2060                              <1> 	;
  2061 00001419 B001                <1> 	mov	al, 1		; scroll 1 line up
  2062                              <1> 		; ah = attribute
  2063 0000141B E939010000          <1> 	jmp	scroll_up
  2064                              <1> ;u4:
  2065                              <1> 	;;int	10h		; video-call return
  2066                              <1> 				; scroll up the screen
  2067                              <1> 				; tty return
  2068                              <1> ;u5:
  2069                              <1> 	;retn			; return to the caller
  2070                              <1> 
  2071                              <1> u6:				; set-cursor-inc
  2072 00001420 FEC6                <1> 	inc	dh		; next row
  2073                              <1> 				; set cursor
  2074                              <1> ;u7:					
  2075                              <1> 	;;mov	ah, 02h
  2076                              <1> 	;;jmp	short u4 	; establish the new cursor
  2077                              <1> 	;call	set_cpos
  2078                              <1> 	;jmp 	short u5
  2079 00001422 E9A8000000          <1> 	jmp     set_cpos
  2080                              <1> 
  2081                              <1> 	; check for control characters
  2082                              <1> u8:
  2083 00001427 7434                <1> 	je	short u9
  2084 00001429 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2085 0000142B 74C6                <1> 	je	short u10
  2086 0000142D 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2087 0000142F 7430                <1> 	je	short u11
  2088 00001431 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2089                              <1> 	;jne	short u0
  2090 00001433 7420                <1> 	je	short bs	; 12/12/2013
  2091                              <1> 	; 12/12/2013 (tab stop)
  2092 00001435 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2093 00001437 75A7                <1> 	jne	short u0
  2094 00001439 88D0                <1> 	mov	al, dl
  2095 0000143B 6698                <1> 	cbw
  2096 0000143D B108                <1> 	mov	cl, 8
  2097 0000143F F6F1                <1> 	div	cl
  2098 00001441 28E1                <1> 	sub	cl, ah
  2099                              <1> ts:
  2100                              <1> 	; 02/09/2014
  2101                              <1> 	; 01/09/2014
  2102 00001443 B020                <1> 	mov	al, 20h
  2103                              <1> tsloop:
  2104                              <1> 	;push	cx
  2105                              <1> 	;push	ax
  2106                              <1> 	; 02/02/2022
  2107 00001445 51                  <1> 	push	ecx
  2108 00001446 50                  <1> 	push	eax
  2109 00001447 30FF                <1> 	xor 	bh, bh
  2110                              <1> 	;mov	bl, [active_page]
  2111 00001449 E881FFFFFF          <1> 	call	m3
  2112                              <1> 	; 02/02/2022
  2113 0000144E 58                  <1> 	pop	eax
  2114 0000144F 59                  <1>  	pop	ecx
  2115                              <1> 	;pop	ax  ; ah = attribute/color
  2116                              <1> 	;pop	cx
  2117 00001450 FEC9                <1> 	dec	cl
  2118 00001452 75F1                <1> 	jnz	short tsloop
  2119 00001454 C3                  <1> 	retn
  2120                              <1> bs:	
  2121                              <1> 	; back space found
  2122 00001455 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2123                              <1> 	;je	short u7 	; set_cursor
  2124 00001457 7476                <1> 	jz	short set_cpos
  2125                              <1> 	;dec	dx     		; no -- just move it back
  2126                              <1> 	; 02/02/2022
  2127 00001459 FECA                <1> 	dec	dl
  2128                              <1> 	;jmp	short u7
  2129 0000145B EB72                <1> 	jmp	short set_cpos
  2130                              <1> 
  2131                              <1> 	; carriage return found
  2132                              <1> u9:
  2133 0000145D B200                <1> 	mov	dl, 0 		; move to first column
  2134                              <1> 	;jmp	short u7
  2135 0000145F EB6E                <1> 	jmp	short set_cpos
  2136                              <1> 
  2137                              <1> 	; line feed found
  2138                              <1> ;u10:
  2139                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2140                              <1> ;	jne	short u6 	; no, just set the cursor
  2141                              <1> ;       jmp     u1              ; yes, scroll the screen
  2142                              <1> 
  2143                              <1> beeper: 
  2144                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2145                              <1> 	; 18/01/2014
  2146                              <1> 	; 03/12/2013
  2147                              <1> 	; bell found
  2148                              <1> u11:
  2149 00001461 FB                  <1> 	sti
  2150 00001462 3A1D[B66B0000]      <1> 	cmp	bl, [active_page]
  2151 00001468 7551                <1> 	jne	short u12	; Do not sound the beep 
  2152                              <1> 				; if it is not written on the active page
  2153 0000146A 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2154 0000146E B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2155                              <1> 	;call	beep		; sound the pod bell
  2156                              <1> 	;jmp	short u5 	; tty_return
  2157                              <1> 	;retn
  2158                              <1> 	
  2159                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2160                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2161                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2162                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2163                              <1> 
  2164                              <1> beep:
  2165                              <1> 	; 07/02/2015
  2166                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2167                              <1> 	; 18/01/2014
  2168                              <1> 	; 03/12/2013
  2169                              <1> 	;
  2170                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2171                              <1> 	;
  2172                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2173                              <1> 	;
  2174                              <1> 	; ENTRY:
  2175                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2176                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2177                              <1> 	; EXIT:			:
  2178                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2179                              <1> 
  2180 00001470 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2181 00001471 FA                  <1> 	cli			; block interrupts during update
  2182 00001472 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2183 00001474 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2184 00001476 EB00                <1> 	jmp	$+2		; I/O delay
  2185 00001478 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2186 0000147A E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2187 0000147C EB00                <1> 	jmp	$+2		; I/O delay
  2188 0000147E 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2189 00001480 E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2190 00001482 E461                <1> 	in	al, PORT_B	; get current setting of port
  2191 00001484 88C4                <1> 	mov	ah, al		; save that setting
  2192 00001486 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2193 00001488 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2194                              <1> 	;popf	; 18/01/2014
  2195 0000148A FB                  <1> 	sti
  2196                              <1> g7:				; 1/64 second per count (bl)
  2197 0000148B B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2198 00001490 E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2199 00001495 FECB                <1> 	dec	bl		; (bl) length count expired?
  2200 00001497 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2201                              <1> 	;
  2202                              <1> 	;pushf			; save interrupt status
  2203 00001499 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2204 0000149A E461                <1> 	in	al, PORT_B	; get current port value
  2205                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2206 0000149C 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2207 0000149E 20C4                <1>         and	ah, al		; someone turned them off during beep
  2208 000014A0 88E0                <1> 	mov	al, ah		; recover value of port
  2209                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2210 000014A2 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2211 000014A4 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2212                              <1> 	;popf			; restore interrupt flag state
  2213 000014A6 FB                  <1> 	sti
  2214 000014A7 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2215 000014AC E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2216                              <1> 	;pushf			; save interrupt status
  2217 000014B1 FA                  <1> 	cli			; block interrupts during update
  2218 000014B2 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2219 000014B4 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2220 000014B6 08E0                <1> 	or	al, ah		; recover value of port_b
  2221 000014B8 E661                <1> 	out	PORT_B, al	; restore speaker status
  2222 000014BA 9D                  <1> 	popf			; restore interrupt flag state
  2223                              <1> u12:	
  2224 000014BB C3                  <1> 	retn
  2225                              <1> 
  2226                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2227                              <1> 
  2228                              <1> WAITF:
  2229                              <1> waitf:
  2230                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2231                              <1> 	; 03/12/2013
  2232                              <1> 	;
  2233                              <1> ;	push	ax		; save work register (ah)	
  2234                              <1> ;waitf1:
  2235                              <1> 				; use timer 1 output bits
  2236                              <1> ;	in	al, PORT_B	; read current counter output status
  2237                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2238                              <1> ;	cmp	al, ah		; did it just change
  2239                              <1> ;	je	short waitf1	; wait for a change in output line
  2240                              <1> ;	;
  2241                              <1> ;	mov	ah, al		; save new lflag state
  2242                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2243                              <1> ;	;
  2244                              <1> ;	pop	ax		; restore (ah)
  2245                              <1> ;	retn			; return (cx)=0
  2246                              <1> 
  2247                              <1> ; 02/02/2022
  2248                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2249                              <1> ; 17/12/2014 (dsectrm2.s)
  2250                              <1> ; WAITF
  2251                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2252                              <1> ;
  2253                              <1> ;---WAITF-----------------------------------------------------------------------
  2254                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2255                              <1> ; ENTRY:
  2256                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2257                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2258                              <1> ; EXIT:
  2259                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2260                              <1> ;	(CX) = 0	
  2261                              <1> ;-------------------------------------------------------------------------------
  2262                              <1> 
  2263                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2264                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2265                              <1> 
  2266                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2267 000014BC 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2268                              <1> 	;push	ax
  2269                              <1> 	; 16/12/2014
  2270                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2271 000014BD D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2272                              <1> ;17/12/2014	
  2273                              <1> ;WAITF1:
  2274                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2275                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2276                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2277                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2278                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2279                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2280                              <1> 	;
  2281                              <1> 	; 17/12/2014
  2282                              <1> 	;
  2283                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2284                              <1> 	;
  2285                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2286                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2287                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2288                              <1> WR_STATE_0:
  2289 000014BF E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2290 000014C1 A810                <1> 	TEST	AL,010H
  2291 000014C3 74FA                <1> 	JZ	SHORT WR_STATE_0
  2292                              <1> WR_STATE_1:
  2293 000014C5 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2294 000014C7 A810                <1> 	TEST	AL,010H
  2295 000014C9 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2296 000014CB E2F2                <1>         LOOP    WR_STATE_0
  2297                              <1> 	;
  2298                              <1> 	;pop	ax
  2299 000014CD 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2300 000014CE C3                  <1> 	RETn				; (CX) = 0
  2301                              <1> 
  2302                              <1> set_cpos:
  2303                              <1> 	; 26/02/2022
  2304                              <1> 	; 02/02/2022
  2305                              <1> 	; 27/06/2015
  2306                              <1> 	; 01/09/2014
  2307                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2308                              <1> 	;
  2309                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2310                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2311                              <1> 	;
  2312                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2313                              <1> 	;
  2314                              <1> 	; SET_CPOS
  2315                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2316                              <1> 	;	NEW X-Y VALUES PASSED
  2317                              <1> 	; INPUT
  2318                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2319                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2320                              <1> 	; OUTPUT
  2321                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2322                              <1> 	;
  2323 000014CF 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2324 000014D2 D0E0                <1>         shl     al, 1   ; word offset
  2325 000014D4 BE[A66B0000]        <1> 	mov	esi, cursor_posn
  2326 000014D9 01C6                <1>         add     esi, eax
  2327 000014DB 668916              <1> 	mov	[esi], dx ; save the pointer
  2328 000014DE 381D[B66B0000]      <1> 	cmp	[active_page], bl
  2329 000014E4 7536                <1> 	jne	short m17
  2330                              <1> 
  2331 000014E6 FA                  <1> 	cli	; 26/02/2022
  2332                              <1> 
  2333                              <1> 	;call	m18	; CURSOR SET
  2334                              <1> ;m17:			; SET_CPOS_RETURN
  2335                              <1> 	; 01/09/2014
  2336                              <1> ;	retn
  2337                              <1> 		; DX = row/column
  2338                              <1> m18:
  2339 000014E7 E835000000          <1> 	call	position ; determine location in regen buffer	
  2340                              <1> 	;mov	cx, [CRT_START]
  2341                              <1> 	; 26/02/2022
  2342 000014EC 0FB70D[A46B0000]    <1> 	movzx	ecx, word [CRT_START]
  2343 000014F3 01C1                <1> 	add	ecx, eax
  2344                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2345                              <1> 			; to the start address (offset) for this page
  2346                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2347                              <1> 	; 26/02/2022
  2348 000014F5 D1E9                <1> 	shr	ecx, 1
  2349 000014F7 B40E                <1> 	mov	ah, 14	; register number for cursor
  2350                              <1> 	
  2351 000014F9 E802000000          <1> 	call	m16	; output value to the 6845
  2352 000014FE FB                  <1> 	sti	; 26/02/2022
  2353 000014FF C3                  <1> 	retn
  2354                              <1> 
  2355                              <1> 	; 26/02/2022
  2356                              <1> 	; 02/02/2022
  2357                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2358                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2359                              <1> m16:
  2360                              <1> 	;cli	; 26/02/2022
  2361                              <1> 	;mov	dx, [addr_6845] ; address register
  2362 00001500 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2363 00001504 88E0                <1> 	mov	al, ah	; get value
  2364 00001506 EE                  <1> 	out	dx, al	; register set
  2365                              <1> 	;inc	dx	; data register
  2366                              <1> 	; 02/02/2022
  2367 00001507 FEC2                <1> 	inc	dl
  2368 00001509 EB00                <1> 	jmp	$+2	; i/o delay
  2369 0000150B 88E8                <1> 	mov	al, ch	; data
  2370 0000150D EE                  <1> 	out	dx, al	
  2371                              <1> 	;dec	dx
  2372                              <1> 	; 02/02/2022	
  2373 0000150E FECA                <1> 	dec	dl
  2374 00001510 88E0                <1> 	mov	al, ah
  2375 00001512 FEC0                <1> 	inc	al	; point to other data register
  2376 00001514 EE                  <1> 	out	dx, al	; set for second register
  2377                              <1> 	;inc	dx
  2378                              <1> 	; 02/02/2022
  2379 00001515 FEC2                <1> 	inc	dl
  2380 00001517 EB00                <1> 	jmp	$+2	; i/o delay
  2381 00001519 88C8                <1> 	mov	al, cl	; second data value
  2382 0000151B EE                  <1> 	out	dx, al
  2383                              <1> 	;sti	; 26/02/2022
  2384                              <1> m17:
  2385 0000151C C3                  <1> 	retn
  2386                              <1> 
  2387                              <1> set_ctype:
  2388                              <1> 	; 07/02/2022
  2389                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2390                              <1> 	;
  2391                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2392                              <1> 
  2393                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2394                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2395                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2396                              <1> ;          OR NO CURSOR AT ALL
  2397                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2398                              <1> 
  2399                              <1> ;------------------------------------------------
  2400                              <1> ; SET_CTYPE
  2401                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2402                              <1> ; INPUT
  2403                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2404                              <1> ; OUTPUT	
  2405                              <1> ;	NONE
  2406                              <1> ;------------------------------------------------
  2407                              <1> 
  2408 0000151D B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2409                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2410                              <1> 	;call	m16	; output cx register
  2411                              <1> 	;retn
  2412                              <1> 	; 07/02/2022
  2413 0000151F EBDF                <1> 	jmp	short m16
  2414                              <1> 
  2415                              <1> position:
  2416                              <1> 	; 26/02/2022
  2417                              <1> 	; 02/02/2022
  2418                              <1> 	; 27/06/2015
  2419                              <1> 	; 02/09/2014
  2420                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2421                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2422                              <1> 	;
  2423                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2424                              <1> 	;
  2425                              <1> 	; POSITION
  2426                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2427                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2428                              <1> 	; INPUT
  2429                              <1> 	;	AX = ROW, COLUMN POSITION
  2430                              <1> 	; OUTPUT
  2431                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2432                              <1> 
  2433                              <1> 		; DX = ROW, COLUMN POSITION
  2434                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2435 00001521 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2436 00001523 B050                <1> 	mov	al, 80	; determine bytes to row	
  2437 00001525 F6E6                <1> 	mul	dh	; row value
  2438                              <1> 	;xor	dh, dh	; 0
  2439                              <1> 	;add	ax, dx	; add column value to the result
  2440                              <1> 	; 26/02/2022
  2441 00001527 00D0                <1> 	add	al, dl
  2442 00001529 80D400              <1> 	adc	ah, 0	
  2443                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2444                              <1> 	; 02/02/2022
  2445 0000152C D1E0                <1> 	shl	eax, 1
  2446                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2447 0000152E C3                  <1> 	retn
  2448                              <1> 
  2449                              <1> find_position:
  2450                              <1> 	; 02/02/2022
  2451                              <1> 	; 27/06/2015
  2452                              <1> 	; 07/09/2014
  2453                              <1> 	; 02/09/2014
  2454                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2455                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2456 0000152F 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2457 00001532 89CE                <1> 	mov	esi, ecx
  2458                              <1> 	;shl	si, 1
  2459                              <1> 	; 02/02/2022
  2460 00001534 D1E6                <1> 	shl	esi, 1
  2461 00001536 668B96[A66B0000]    <1> 	mov	dx, [esi+cursor_posn]
  2462 0000153D 7409                <1> 	jz	short p21
  2463                              <1> 	;xor	si, si
  2464                              <1> 	; 02/02/2022
  2465 0000153F 31F6                <1> 	xor	esi, esi
  2466                              <1> p20:
  2467                              <1> 	;add	si, [CRT_LEN]
  2468 00001541 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2469 00001546 E2F9                <1> 	loop	p20
  2470                              <1> p21:
  2471 00001548 6621D2              <1> 	and	dx, dx
  2472 0000154B 7407                <1> 	jz	short p22
  2473 0000154D E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2474 00001552 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2475                              <1> p22:	
  2476                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2477                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2478                              <1> 	;add	dx, 6	; point at status port
  2479 00001554 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2480                              <1> 	; cx = 0
  2481 00001558 C3                  <1> 	retn
  2482                              <1> 
  2483                              <1> scroll_up:
  2484                              <1> 	; 02/02/2022 (simplified scroll up)
  2485                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2486                              <1> 	; 16/01/2016
  2487                              <1> 	; 07/09/2014
  2488                              <1> 	; 02/09/2014
  2489                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2490                              <1> 	; 04/04/2014
  2491                              <1> 	; 04/12/2013
  2492                              <1> 	;
  2493                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2494                              <1> 	;
  2495                              <1> 	; SCROLL UP
  2496                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2497                              <1> 	;	ON THE SCREEN
  2498                              <1> 	; INPUT
  2499                              <1> 	;	(AH) = CURRENT CRT MODE
  2500                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2501                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2502                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2503                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2504                              <1> 	;	(DS) = DATA SEGMENT
  2505                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2506                              <1> 	; OUTPUT
  2507                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2508                              <1> 	;
  2509                              <1> 	;	bh = 0  (02/09/2014)
  2510                              <1> 	;
  2511                              <1> 	; ((ah = 3))
  2512                              <1> 	; cl = left upper column
  2513                              <1> 	; ch = left upper row
  2514                              <1> 	; dl = right lower column
  2515                              <1> 	; dh = right lower row
  2516                              <1> 	;
  2517                              <1> 	; al = line count 
  2518                              <1> 	; ah = attribute to be used on blanked line
  2519                              <1> 	; bl = video page number (0 to 7)
  2520                              <1> 	; 
  2521                              <1> 
  2522                              <1> 	; 02/02/2022 'scroll_up' code
  2523                              <1> 	; ------------------------------------------------------
  2524                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2525                              <1> 
  2526                              <1> 	; INPUT:
  2527                              <1> 	;		
  2528                              <1> 	; al = line count 
  2529                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2530                              <1> 	; ah = attribute to be used on blanked line
  2531                              <1> 	; bl = video page number (0 to 7)
  2532                              <1> 
  2533                              <1> 	;cli
  2534 00001559 31C9                <1> 	xor	ecx, ecx
  2535 0000155B 88C1                <1> 	mov	cl, al ; line count (cl)
  2536 0000155D BE00800B00          <1> 	mov	esi, 0B8000h
  2537 00001562 3A1D[B66B0000]      <1> 	cmp	bl, [active_page]
  2538 00001568 7411                <1> 	je	short n1
  2539 0000156A 20DB                <1> 	and	bl, bl
  2540 0000156C 7422                <1> 	jz	short n3
  2541 0000156E 88DD                <1> 	mov	ch, bl ; video page number
  2542                              <1> n0:
  2543 00001570 6681C6A00F          <1> 	add	si, 25*80*2
  2544 00001575 FECD                <1> 	dec	ch
  2545 00001577 75F7                <1> 	jnz	short n0
  2546 00001579 EB15                <1> 	jmp	short n3
  2547                              <1> n1:
  2548 0000157B 660335[A46B0000]    <1> 	add	si, [CRT_START]
  2549                              <1> 	;
  2550 00001582 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here	
  2551                              <1> n2:			 ; wait_display_enable
  2552 00001586 EC                  <1> 	in	al, dx	 ; get port
  2553 00001587 A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2554 00001589 74FB                <1> 	jz	short n2 ; wait_display_enable
  2555 0000158B B025                <1> 	mov	al, 25h
  2556 0000158D B2D8                <1> 	mov	dl, 0D8h ; address control port
  2557 0000158F EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2558                              <1> n3:
  2559                              <1> 	; cl = line count
  2560                              <1> 	; ah = attribute/color
  2561 00001590 89F7                <1> 	mov	edi, esi
  2562 00001592 20C9                <1> 	and	cl, cl
  2563 00001594 741F                <1> 	jz	short n6
  2564 00001596 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2565 0000159B 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2566 0000159F F366A5              <1> 	rep	movsw
  2567 000015A2 B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2568                              <1> n4:
  2569                              <1> 	; ah = character attribute/cocor
  2570 000015A4 B020                <1> 	mov	al, 20h ; fill with blanks
  2571 000015A6 F366AB              <1> 	rep	stosw
  2572                              <1> 
  2573 000015A9 3A1D[B66B0000]      <1> 	cmp	bl, [active_page]
  2574 000015AF 7503                <1> 	jne	short n5
  2575                              <1> 
  2576                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2577 000015B1 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3	
  2578                              <1> 	;mov	dx, 03D8h ; always set color card port
  2579 000015B3 EE                  <1> 	out	dx, al
  2580                              <1> n5:
  2581 000015B4 C3                  <1> 	retn
  2582                              <1> n6:
  2583                              <1> 	; clear video page
  2584 000015B5 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2585 000015B9 EBE9                <1> 	jmp	short n4
  2586                              <1> 
  2587                              <1> 	; 26/02/2022
  2588                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2589                              <1> 	; ------------------------------------------------------
  2590                              <1> 
  2591                              <1> 	; Test	Line Count
  2592                              <1> 	or	al, al
  2593                              <1> 	jz	short al_set
  2594                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2595                              <1> 	sub	bh, ch
  2596                              <1> 	inc	bh	; adjust difference by 1
  2597                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2598                              <1> 	jne	short al_set ; if not the we're all set
  2599                              <1> 	xor	al, al	; otherwise set al to zero
  2600                              <1> al_set:
  2601                              <1> 	xor	bh, bh	; 0
  2602                              <1> 	;push	ax
  2603                              <1> 	push	eax ; 26/02/2022
  2604                              <1> 	;mov 	esi, [crt_base]
  2605                              <1>         mov     esi, 0B8000h  
  2606                              <1>         cmp     bl, [active_page]
  2607                              <1> 	jne	short n0
  2608                              <1> 	;
  2609                              <1>         mov     ax, [CRT_START]
  2610                              <1>         add     si, ax
  2611                              <1>         jmp     short n1
  2612                              <1> n0:
  2613                              <1>         and     bl, bl
  2614                              <1> 	jz	short n1
  2615                              <1> 	mov	al, bl
  2616                              <1> n0x:
  2617                              <1>         ;add    si, [CRT_LEN]
  2618                              <1>         ;add    esi, 80*25*2 
  2619                              <1>         add     si, 80*25*2
  2620                              <1>         dec	al
  2621                              <1> 	jnz	short n0x
  2622                              <1> n1:	
  2623                              <1>         ; Scroll position
  2624                              <1> 	;push	dx ; 26/02/2022
  2625                              <1> 	mov	dx, cx	; now, upper left position in DX
  2626                              <1> 	call	position
  2627                              <1> 	add	esi, eax
  2628                              <1> 	mov	edi, esi
  2629                              <1> 	;pop	dx	; lower right position in DX
  2630                              <1> 	sub	dx, cx
  2631                              <1> 	inc	dh	; dh = #rows 
  2632                              <1> 	inc	dl	; dl = #cols in block
  2633                              <1> 	;pop	ax	; al = line count, ah = attribute
  2634                              <1> 	pop	eax ; 26/02/2022
  2635                              <1> 	xor	ecx, ecx
  2636                              <1> 	mov	cx, ax
  2637                              <1> 	;mov	ah, [CRT_COLS]
  2638                              <1> 	mov	ah, 80
  2639                              <1> 	mul	ah	; determine offset to from address
  2640                              <1> 	add	ax, ax  ; *2 for attribute byte
  2641                              <1> 	;
  2642                              <1> 	;push	ax	; offset 
  2643                              <1> 	;push	dx
  2644                              <1> 	; 26/02/2022
  2645                              <1> 	push	eax
  2646                              <1> 	push	edx
  2647                              <1> 	;
  2648                              <1> 	; 04/04/2014
  2649                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2650                              <1> n8:                      ; wait_display_enable
  2651                              <1>         in      al, dx   ; get port
  2652                              <1> 	test	al, RVRT ; wait for vertical retrace
  2653                              <1> 	jz	short n8 ; wait_display_enable
  2654                              <1> 	mov	al, 25h
  2655                              <1> 	mov	dl, 0D8h ; address control port
  2656                              <1> 	out	dx, al	; turn off video during vertical retrace
  2657                              <1> 	;pop	dx	; #rows, #cols
  2658                              <1>        	;pop	ax	; offset
  2659                              <1> 	; 26/02/2022
  2660                              <1> 	pop	edx
  2661                              <1> 	pop	eax
  2662                              <1> 	xchg	ax, cx	; 
  2663                              <1> 	; ecx = offset, al = line count, ah = attribute
  2664                              <1> ;n9:
  2665                              <1> 	or	al, al
  2666                              <1>         jz      short n3 
  2667                              <1>         add     esi, ecx ; from address for scroll
  2668                              <1> 	mov	bh, dh  ; #rows in block
  2669                              <1> 	sub	bh, al	; #rows to be moved
  2670                              <1> n2:
  2671                              <1> 	; Move rows
  2672                              <1> 	mov	cl, dl	; get # of cols to move
  2673                              <1> 	push	esi
  2674                              <1> 	push	edi	; save start address
  2675                              <1> n10:
  2676                              <1> 	movsw		; move that line on screen
  2677                              <1> 	dec	cl
  2678                              <1>         jnz     short n10
  2679                              <1> 	pop	edi
  2680                              <1> 	pop	esi	; recover addresses
  2681                              <1>         ;mov    cl, [CRT_COLS] 
  2682                              <1> 	;add	cl, cl
  2683                              <1>         ;mov    ecx, 80*2
  2684                              <1>         mov     cx, 80*2
  2685                              <1>         add     esi, ecx  ; next line
  2686                              <1>         add     edi, ecx
  2687                              <1> 	dec	bh	 ; count of lines to move
  2688                              <1> 	jnz	short n2 ; row loop
  2689                              <1> 	; bh = 0
  2690                              <1> 	mov	dh, al	 ; #rows	
  2691                              <1> n3:
  2692                              <1> 	; attribute in ah
  2693                              <1> 	mov	al, ' '	 ; fill with blanks
  2694                              <1> n3x:
  2695                              <1> 	; Clear rows
  2696                              <1>                 ; dh =  #rows
  2697                              <1>         mov	cl, dl	; get # of cols to clear
  2698                              <1>         push    edi     ; save address
  2699                              <1> n11:
  2700                              <1>         stosw           ; store fill character
  2701                              <1> 	dec	cl
  2702                              <1>         jnz     short n11
  2703                              <1>         pop     edi     ; recover address
  2704                              <1> 	;mov	cl, [CRT_COLS]
  2705                              <1> 	;add	cl, cl
  2706                              <1>         ;mov    ecx, 80*2
  2707                              <1>         mov	cl, 80*2
  2708                              <1>         add     edi, ecx
  2709                              <1> 	dec	dh
  2710                              <1> 	jnz	short n3x ; 16/01/2016
  2711                              <1> 	;
  2712                              <1> 	cmp	bl, [active_page]
  2713                              <1> 	jne	short n6
  2714                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2715                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2716                              <1> 	mov	dx, 03D8h ; always set color card port
  2717                              <1> 	out	dx, al
  2718                              <1> n6:
  2719                              <1> 	retn
  2720                              <1> 
  2721                              <1> %endif
  2722                              <1> 
  2723                              <1> write_c_current:
  2724                              <1> 	; 02/02/2022
  2725                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2726                              <1> 	; 18/01/2014
  2727                              <1> 	; 04/12/2013
  2728                              <1> 	;
  2729                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2730                              <1> 	;
  2731                              <1> 	; WRITE_C_CURRENT
  2732                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2733                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2734                              <1> 	; INPUT	
  2735                              <1> 	;	(AH) = CURRENT CRT MODE
  2736                              <1> 	;	(BH) = DISPLAY PAGE
  2737                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2738                              <1> 	;	(AL) = CHAR TO WRITE
  2739                              <1> 	;	(DS) = DATA SEGMENT
  2740                              <1> 	;	(ES) = REGEN SEGMENT
  2741                              <1> 	; OUTPUT
  2742                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2743                              <1> 
  2744 000015BB FA                  <1> 	cli		
  2745                              <1> 	; bl = video page
  2746                              <1> 	; al = character
  2747                              <1> 	; ah = color/attribute
  2748                              <1> 	;push	dx
  2749                              <1> 	;push	ax	; save character & attribute/color
  2750                              <1> 	; 02/02/2022
  2751 000015BC 52                  <1> 	push	edx
  2752 000015BD 50                  <1> 	push	eax
  2753 000015BE E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2754                              <1> 	; esi = regen location
  2755                              <1> 	; dx = status port
  2756                              <1> 	;
  2757                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2758                              <1> 	;
  2759                              <1> p41:			; wait for horizontal retrace is low or vertical
  2760 000015C3 FB                  <1> 	sti		; enable interrupts first
  2761 000015C4 3A1D[B66B0000]      <1>         cmp     bl, [active_page]
  2762 000015CA 7510                <1> 	jne	short p44 
  2763 000015CC FA                  <1> 	cli 		; block interrupts for single loop
  2764 000015CD EC                  <1> 	in	al, dx	; get status from the adapter
  2765 000015CE A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2766 000015D0 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2767 000015D2 A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2768 000015D4 75ED                <1> 	jnz	short p41 ; wait until it is
  2769                              <1> p42:			; wait for either retrace high
  2770 000015D6 EC                  <1> 	in	al, dx	; get status again
  2771 000015D7 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2772 000015D9 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2773                              <1> p43:	
  2774 000015DB FB                  <1> 	sti
  2775                              <1> p44:
  2776                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2777                              <1> 	; 02/02/2022
  2778 000015DC 58                  <1> 	pop	eax
  2779 000015DD 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2780                              <1> 			; Retro UNIX 386 v1 feature only!
  2781 000015E3 668906              <1> 	mov	[esi], ax
  2782                              <1> 	;pop	dx
  2783                              <1> 	; 02/02/2022
  2784 000015E6 5A                  <1> 	pop	edx
  2785 000015E7 C3                  <1> 	retn
  2786                              <1> 
  2787                              <1> %if 0	; 02/02/2022
  2788                              <1> 
  2789                              <1> set_mode:
  2790                              <1> 	; 02/02/2022
  2791                              <1> 	; 16/01/2016
  2792                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2793                              <1> 	;
  2794                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2795                              <1> 
  2796                              <1> ;------------------------------------------------------
  2797                              <1> ; SET MODE					      :
  2798                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2799                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2800                              <1> ; INPUT						      :
  2801                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2802                              <1> ; OUTPUT					      :
  2803                              <1> ;	NONE					      :
  2804                              <1> ;------------------------------------------------------
  2805                              <1> 
  2806                              <1> 	push	edi ; 16/01/2016
  2807                              <1> 	push	ebx
  2808                              <1> 	push	edx
  2809                              <1> 	push	ecx ; 16/01/2016
  2810                              <1>         push    eax
  2811                              <1> 
  2812                              <1> 	;mov	dx, 03D4h 	; address or color card
  2813                              <1> 	mov	al, 3
  2814                              <1> ;M8:
  2815                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2816                              <1> 	mov	al, 29h
  2817                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2818                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2819                              <1> 	;push	dx  		; save port value
  2820                              <1> 	;add	dx, 4		; point to control register
  2821                              <1> 	mov	dx, 3D8h
  2822                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2823                              <1> 	;pop	dx
  2824                              <1> ;M9:
  2825                              <1> 	mov	ebx, video_params ; initialization table
  2826                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2827                              <1> 	;xchg 	ah, al
  2828                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2829                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2830                              <1> 	
  2831                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2832                              <1> 	; 02/02/2022
  2833                              <1> 	; dx = 3D8h
  2834                              <1> 	xor	ecx, ecx
  2835                              <1> 	mov	cl, 16
  2836                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2837                              <1> M10:			;  initialization loop
  2838                              <1> 	mov	al, ah 	; get 6845 register number
  2839                              <1> 	out	dx, al
  2840                              <1> 	;inc	dx      ; point to data port
  2841                              <1> 	; 02/02/2022
  2842                              <1> 	inc	dl ; 3D9h
  2843                              <1> 	inc	ah	; next register value
  2844                              <1> 	mov	al, [ebx] ; get table value
  2845                              <1> 	out	dx, al	; out to chip
  2846                              <1> 	inc	ebx	; next in table
  2847                              <1> 	;dec	dx	; back to pointer register
  2848                              <1> 	; 02/02/2022
  2849                              <1> 	dec	dl ; 3D8h
  2850                              <1> 	loop	M10	; do the whole table
  2851                              <1> 	
  2852                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2853                              <1> 	;xor	ax, ax  
  2854                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2855                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2856                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2857                              <1> 	; black background, light gray characeter color, space character
  2858                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2859                              <1> ;M13:			  ; clear buffer
  2860                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2861                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2862                              <1> 
  2863                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2864                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2865                              <1> 			 ; prepare to output to video enable port
  2866                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2867                              <1> 	; 02/02/2022
  2868                              <1> 	;mov	dx, 3D8h
  2869                              <1> 	; 
  2870                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2871                              <1> 	mov	al, 29h
  2872                              <1> 	out	dx, al	 ; set video enable port
  2873                              <1> 
  2874                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2875                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2876                              <1> 	;
  2877                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2878                              <1> 	;
  2879                              <1> ;-----	SET CURSOR POSITIONS
  2880                              <1> 	;push	edi
  2881                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2882                              <1> 	mov	edi, cursor_posn
  2883                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2884                              <1> 	xor	eax, eax
  2885                              <1> 	rep 	stosd	; fill with zeroes
  2886                              <1> 	;pop	edi
  2887                              <1> 
  2888                              <1> ;-----	SET UP OVERSCAN REGISTER
  2889                              <1> 	inc	dx	; set overscan port to a default
  2890                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2891                              <1> ;M14:
  2892                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2893                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2894                              <1> 
  2895                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2896                              <1> 	;
  2897                              <1> 	pop	eax
  2898                              <1> 	pop	ecx ; 16/01/2016
  2899                              <1> 	pop	edx
  2900                              <1> 	pop	ebx
  2901                              <1> 	pop	edi ; 16/01/2016
  2902                              <1> 	retn
  2903                              <1> 
  2904                              <1> %endif
  2905                              <1> 	
  2906                              <1> tty_sw:
  2907                              <1> 	; 02/02/2022
  2908                              <1> 	; 30/06/2015
  2909                              <1> 	; 27/06/2015 
  2910                              <1> 	; 07/09/2014
  2911                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2912                              <1> 	;
  2913                              <1> 	; (Modified registers : EAX)
  2914                              <1> 	;
  2915                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2916                              <1> 	;
  2917                              <1> ;act_disp_page:
  2918                              <1> 	; 30/06/2015
  2919                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2920                              <1> 	; 10/12/2013
  2921                              <1> 	; 04/12/2013
  2922                              <1> 	;
  2923                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2924                              <1> 	;
  2925                              <1> 	; ACT_DISP_PAGE
  2926                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2927                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2928                              <1> 	; INPUT
  2929                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2930                              <1> 	; OUTPUT
  2931                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2932                              <1> 
  2933                              <1> 	;cli
  2934                              <1> 
  2935 000015E8 53                  <1> 	push	ebx
  2936                              <1> 	;push	cx
  2937                              <1> 	;push	dx
  2938                              <1> 	; 02/02/2022
  2939 000015E9 51                  <1> 	push	ecx
  2940 000015EA 52                  <1> 	push	edx
  2941                              <1> 	;
  2942 000015EB A2[B66B0000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2943                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2944                              <1> 	;mov	cx, 25*80*2
  2945                              <1> 	; 02/02/2022
  2946 000015F0 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2947                              <1> 	; 27/06/2015
  2948 000015F5 0FB6D8              <1> 	movzx	ebx, al
  2949                              <1> 	; 02/02/2022
  2950 000015F8 89D8                <1> 	mov	eax, ebx
  2951                              <1> 	;
  2952                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2953                              <1> 	;mul 	cx	; display page times regen length
  2954                              <1> 	; 02/02/2022
  2955 000015FA F7E1                <1> 	mul	ecx	
  2956                              <1> 	; 10/12/2013
  2957 000015FC 66A3[A46B0000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2958                              <1> 	;mov	cx, ax	; start address to cx
  2959                              <1> 	; 02/02/2022
  2960 00001602 89C1                <1> 	mov	ecx, eax
  2961                              <1> 	;sar	cx, 1
  2962                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2963                              <1> 	; 02/02/2022
  2964 00001604 D1E9                <1> 	shr	ecx, 1
  2965 00001606 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2966 00001608 E8F3FEFFFF          <1> 	call	m16
  2967                              <1> 	;sal	bx, 1
  2968                              <1> 	; 01/09/2014
  2969 0000160D D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2970 0000160F 81C3[A66B0000]      <1> 	add	ebx, cursor_posn
  2971 00001615 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2972 00001618 E8CAFEFFFF          <1> 	call	m18
  2973                              <1> 	;
  2974                              <1> 	;pop	dx
  2975                              <1> 	;pop	cx
  2976                              <1> 	; 02/02/2022
  2977 0000161D 5A                  <1> 	pop	edx
  2978 0000161E 59                  <1> 	pop	ecx
  2979 0000161F 5B                  <1> 	pop	ebx
  2980                              <1> 	;
  2981                              <1> 	;sti
  2982                              <1> 	;
  2983 00001620 C3                  <1> 	retn
  2984                              <1> 
  2985                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2986                              <1> 
  2987                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1880                                  
  1881                                  setup_rtc_int:
  1882                                  ; source: http://wiki.osdev.org/RTC
  1883 00001621 FA                      	cli		; disable interrupts
  1884                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1885                                  	; in order to change this ...
  1886                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1887                                  	; (rate must be above 2 and not over 15)
  1888                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1889 00001622 B08A                    	mov	al, 8Ah 
  1890 00001624 E670                    	out	70h, al ; set index to register A, disable NMI
  1891 00001626 90                      	nop
  1892 00001627 E471                    	in	al, 71h ; get initial value of register A
  1893 00001629 88C4                    	mov 	ah, al
  1894 0000162B 80E4F0                  	and	ah, 0F0h
  1895 0000162E B08A                    	mov	al, 8Ah 
  1896 00001630 E670                    	out	70h, al ; reset index to register A
  1897 00001632 88E0                    	mov	al, ah
  1898 00001634 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1899 00001636 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1900                                  	; enable RTC interrupt
  1901 00001638 B08B                    	mov	al, 8Bh ;
  1902 0000163A E670                    	out	70h, al ; select register B and disable NMI
  1903 0000163C 90                      	nop
  1904 0000163D E471                    	in	al, 71h ; read the current value of register B
  1905 0000163F 88C4                    	mov	ah, al  ;
  1906 00001641 B08B                    	mov 	al, 8Bh ;
  1907 00001643 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1908 00001645 88E0                    	mov	al, ah  ;
  1909 00001647 0C40                    	or	al, 40h ;
  1910 00001649 E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1911 0000164B FB                      	sti
  1912 0000164C C3                      	retn
  1913                                  
  1914                                  ; Write memory information
  1915                                  ; Temporary Code
  1916                                  ; 06/11/2014
  1917                                  ; 14/08/2015 
  1918                                  memory_info:	
  1919 0000164D A1[8C6B0000]            	mov	eax, [memory_size] ; in pages
  1920 00001652 50                      	push	eax
  1921 00001653 C1E00C                  	shl	eax, 12		   ; in bytes
  1922 00001656 BB0A000000              	mov	ebx, 10
  1923 0000165B 89D9                    	mov	ecx, ebx	   ; 10
  1924 0000165D BE[F1670000]            	mov	esi, mem_total_b_str	
  1925 00001662 E8AE000000              	call	bintdstr
  1926 00001667 58                      	pop	eax
  1927 00001668 B107                    	mov	cl, 7
  1928 0000166A BE[15680000]            	mov	esi, mem_total_p_str
  1929 0000166F E8A1000000              	call	bintdstr	
  1930                                  	; 14/08/2015
  1931 00001674 E8B9000000              	call	calc_free_mem
  1932                                  	; edx = calculated free pages
  1933                                  	; ecx = 0
  1934 00001679 A1[906B0000]            	mov 	eax, [free_pages]
  1935 0000167E 39D0                    	cmp	eax, edx ; calculated free mem value 
  1936                                  		; and initial free mem value are same or not?
  1937 00001680 751D                    	jne 	short pmim ; print mem info with '?' if not
  1938 00001682 52                      	push 	edx ; free memory in pages	
  1939                                  	;mov 	eax, edx
  1940 00001683 C1E00C                  	shl	eax, 12 ; convert page count
  1941                                  			; to byte count
  1942 00001686 B10A                    	mov	cl, 10
  1943 00001688 BE[35680000]            	mov	esi, free_mem_b_str
  1944 0000168D E883000000              	call	bintdstr
  1945 00001692 58                      	pop	eax
  1946 00001693 B107                    	mov	cl, 7
  1947 00001695 BE[59680000]            	mov	esi, free_mem_p_str
  1948 0000169A E876000000              	call	bintdstr
  1949                                  pmim:
  1950 0000169F BE[DF670000]            	mov	esi, msg_memory_info
  1951                                  pmim_nb:	
  1952 000016A4 AC                      	lodsb
  1953 000016A5 08C0                    	or	al, al
  1954 000016A7 740D                    	jz	short pmim_ok
  1955 000016A9 56                      	push	esi
  1956 000016AA 31DB                    	xor	ebx, ebx ; 0
  1957                                  			; Video page 0 (bl=0)
  1958 000016AC B407                    	mov	ah, 07h ; Black background, 
  1959                                  			; light gray forecolor
  1960 000016AE E812FDFFFF              	call	write_tty
  1961 000016B3 5E                      	pop	esi
  1962 000016B4 EBEE                    	jmp	short pmim_nb
  1963                                  pmim_ok:
  1964 000016B6 C3                      	retn
  1965                                  
  1966                                  ; Convert binary number to hexadecimal string
  1967                                  ; 10/05/2015  
  1968                                  ; dsectpm.s (28/02/2015)
  1969                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1970                                  ; 01/12/2014
  1971                                  ; 25/11/2014
  1972                                  ;
  1973                                  bytetohex:
  1974                                  	; INPUT ->
  1975                                  	; 	AL = byte (binary number)
  1976                                  	; OUTPUT ->
  1977                                  	;	AX = hexadecimal string
  1978                                  	;
  1979 000016B7 53                      	push	ebx
  1980 000016B8 31DB                    	xor	ebx, ebx
  1981 000016BA 88C3                    	mov	bl, al
  1982 000016BC C0EB04                  	shr	bl, 4
  1983 000016BF 8A9B[05170000]          	mov	bl, [ebx+hexchrs]
  1984 000016C5 86D8                    	xchg	bl, al
  1985 000016C7 80E30F                  	and	bl, 0Fh
  1986 000016CA 8AA3[05170000]          	mov	ah, [ebx+hexchrs]
  1987 000016D0 5B                      	pop	ebx	
  1988 000016D1 C3                      	retn
  1989                                  
  1990                                  wordtohex:
  1991                                  	; INPUT ->
  1992                                  	; 	AX = word (binary number)
  1993                                  	; OUTPUT ->
  1994                                  	;	EAX = hexadecimal string
  1995                                  	;
  1996 000016D2 53                      	push	ebx
  1997 000016D3 31DB                    	xor	ebx, ebx
  1998 000016D5 86E0                    	xchg	ah, al
  1999 000016D7 6650                    	push	ax
  2000 000016D9 88E3                    	mov	bl, ah
  2001 000016DB C0EB04                  	shr	bl, 4
  2002 000016DE 8A83[05170000]          	mov	al, [ebx+hexchrs]
  2003 000016E4 88E3                    	mov	bl, ah
  2004 000016E6 80E30F                  	and	bl, 0Fh
  2005 000016E9 8AA3[05170000]          	mov	ah, [ebx+hexchrs]
  2006 000016EF C1E010                  	shl	eax, 16
  2007 000016F2 6658                    	pop	ax
  2008 000016F4 5B                      	pop	ebx
  2009 000016F5 EBC0                    	jmp	short bytetohex
  2010                                  	;mov	bl, al
  2011                                  	;shr	bl, 4
  2012                                  	;mov	bl, [ebx+hexchrs]
  2013                                  	;xchg	bl, al	 	
  2014                                  	;and	bl, 0Fh
  2015                                  	;mov	ah, [ebx+hexchrs]
  2016                                  	;pop	ebx	
  2017                                  	;retn
  2018                                  
  2019                                  dwordtohex:
  2020                                  	; INPUT ->
  2021                                  	; 	EAX = dword (binary number)
  2022                                  	; OUTPUT ->
  2023                                  	;	EDX:EAX = hexadecimal string
  2024                                  	;
  2025 000016F7 50                      	push	eax
  2026 000016F8 C1E810                  	shr	eax, 16
  2027 000016FB E8D2FFFFFF              	call	wordtohex
  2028 00001700 89C2                    	mov	edx, eax
  2029 00001702 58                      	pop	eax
  2030                                  	;call	wordtohex
  2031                                  	;retn
  2032                                  	; 02/01/2022
  2033 00001703 EBCD                    	jmp	short wordtohex
  2034                                  
  2035                                  ; 10/05/2015
  2036                                  hex_digits:
  2037                                  hexchrs:
  2038 00001705 303132333435363738-     	db '0123456789ABCDEF'
  2038 0000170E 39414243444546     
  2039                                  
  2040                                  ; Convert binary number to decimal/numeric string
  2041                                  ; 06/11/2014
  2042                                  ; Temporary Code
  2043                                  ;
  2044                                  
  2045                                  bintdstr:
  2046                                  	; EAX = binary number
  2047                                  	; ESI = decimal/numeric string address
  2048                                  	; EBX = divisor (10)
  2049                                  	; ECX = string length (<=10)
  2050 00001715 01CE                    	add	esi, ecx
  2051                                  btdstr0:
  2052 00001717 4E                      	dec	esi
  2053 00001718 31D2                    	xor	edx, edx
  2054 0000171A F7F3                    	div	ebx
  2055 0000171C 80C230                  	add	dl, 30h
  2056 0000171F 8816                    	mov	[esi], dl
  2057 00001721 FEC9                    	dec	cl
  2058 00001723 740C                    	jz	short btdstr2 ; 02/01/2022 (short jump)
  2059 00001725 09C0                    	or	eax, eax
  2060 00001727 75EE                    	jnz	short btdstr0
  2061                                  btdstr1:
  2062 00001729 4E                      	dec	esi
  2063 0000172A C60620                          mov     byte [esi], 20h ; blank space
  2064 0000172D FEC9                    	dec	cl
  2065 0000172F 75F8                    	jnz	short btdstr1
  2066                                  btdstr2:
  2067 00001731 C3                      	ret
  2068                                  
  2069                                  ; Calculate free memory pages on M.A.T.
  2070                                  ; 06/11/2014
  2071                                  ; Temporary Code
  2072                                  ;
  2073                                  
  2074                                  calc_free_mem:
  2075 00001732 31D2                    	xor	edx, edx
  2076                                  	;xor	ecx, ecx
  2077                                  	;mov	cx, [mat_size] ; in pages
  2078                                  	; 02/01/2022
  2079 00001734 8B0D[A06B0000]          	mov	ecx, [mat_size] ; in pages
  2080 0000173A C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2081 0000173D BE00001000              	mov	esi, MEM_ALLOC_TBL
  2082                                  cfm0:
  2083 00001742 AD                      	lodsd
  2084 00001743 51                      	push	ecx
  2085 00001744 B920000000              	mov	ecx, 32
  2086                                  cfm1:
  2087 00001749 D1E8                    	shr	eax, 1
  2088 0000174B 7301                    	jnc	short cfm2
  2089 0000174D 42                      	inc	edx
  2090                                  cfm2:
  2091 0000174E E2F9                    	loop	cfm1
  2092 00001750 59                      	pop	ecx
  2093 00001751 E2EF                    	loop	cfm0
  2094 00001753 C3                      	ret
  2095                                  
  2096                                  %include 'diskio.inc'  ; 07/03/2015
  2097                              <1> ; Retro UNIX 386 v1.1 Kernel - DISKIO.INC
  2098                              <1> ; Last Modification: 24/12/2021
  2099                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2100                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2101                              <1> 
  2102                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2103                              <1> 
  2104                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2105                              <1> 
  2106                              <1> ; 06/02/2015
  2107                              <1> diskette_io:
  2108 00001754 9C                  <1> 	pushfd
  2109 00001755 0E                  <1> 	push 	cs
  2110 00001756 E809000000          <1> 	call 	DISKETTE_IO_1
  2111 0000175B C3                  <1> 	retn
  2112                              <1> 	
  2113                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2114                              <1> ;//////////////////////////////////////////////////////
  2115                              <1> 
  2116                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2117                              <1> ; 20/02/2015
  2118                              <1> ; 06/02/2015 (unix386.s)
  2119                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2120                              <1> ;
  2121                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2122                              <1> ;
  2123                              <1> ; ADISK.EQU
  2124                              <1> 
  2125                              <1> ;----- Wait control constants 
  2126                              <1> 
  2127                              <1> ;amount of time to wait while RESET is active.
  2128                              <1> 
  2129                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2130                              <1> 					;at 250 KBS xfer rate.
  2131                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2132                              <1> 
  2133                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2134                              <1> 					;status register to become valid
  2135                              <1> 					;before re-reading.
  2136                              <1> 
  2137                              <1> ;After sending a byte to NEC, status register may remain
  2138                              <1> ;incorrectly set for 24 us.
  2139                              <1> 
  2140                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2141                              <1> 					;RQM low.
  2142                              <1> 
  2143                              <1> ; COMMON.MAC
  2144                              <1> ;
  2145                              <1> ;	Timing macros
  2146                              <1> ;
  2147                              <1> 
  2148                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2149                              <1> 		jmp short $+2
  2150                              <1> %endmacro		
  2151                              <1> 
  2152                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2153                              <1> 		jmp short $+2
  2154                              <1> 		jmp short $+2
  2155                              <1> %endmacro
  2156                              <1> 
  2157                              <1> %macro		NEWIODELAY 0
  2158                              <1> 		out	0EBh,al
  2159                              <1> %endmacro 
  2160                              <1> 
  2161                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2162                              <1> ;;; WAIT_FOR_MEM
  2163                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2164                              <1> ;WAIT_FDU_INT_HI	equ	1
  2165                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2166                              <1> ;;; WAIT_FOR_PORT
  2167                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2168                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2169                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2170                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2171                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2172                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2173                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2174                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2175                              <1> ;;; WAIT_REFRESH
  2176                              <1> ;amount of time to wait for head settle, per unit in parameter
  2177                              <1> ;table = 1 ms.
  2178                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2179                              <1> 
  2180                              <1> 
  2181                              <1> ; //////////////// DISKETTE I/O ////////////////
  2182                              <1> 
  2183                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2184                              <1> 
  2185                              <1> ;----------------------------------------
  2186                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2187                              <1> ;----------------------------------------
  2188                              <1> 
  2189                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2190                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2191                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2192                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2193                              <1> 
  2194                              <1> ;----------------------------------------
  2195                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2196                              <1> ;-------------------------------------------------------------------------------
  2197                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2198                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2199                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2200                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2201                              <1> 
  2202                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2203                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2204                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2205                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2206                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2207                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2208                              <1> 
  2209                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2210                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2211                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2212                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2213                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2214                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2215                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2216                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2217                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2218                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2219                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2220                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2221                              <1> 
  2222                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2223                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2224                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2225                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2226                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2227                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2228                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2229                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2230                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2231                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2232                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2233                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2234                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2235                              <1> 
  2236                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2237                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2238                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2239                              <1> 
  2240                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2241                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2242                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2243                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2244                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2245                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2246                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2247                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2248                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2249                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2250                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2251                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2252                              <1> 
  2253                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2254                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2255                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2256                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2257                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2258                              <1> 
  2259                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2260                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2261                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2262                              <1> INTA01		EQU	021H		; 8259 PORT
  2263                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2264                              <1> INTB01		EQU	0A1H		;
  2265                              <1> 
  2266                              <1> ;-------------------------------------------------------------------------------
  2267                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2268                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2269                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2270                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2271                              <1> ;-------------------------------------------------------------------------------
  2272                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2273                              <1> 
  2274                              <1> ;-------------------------------------------------------------------------------
  2275                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2276                              <1> 
  2277                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2278                              <1> ; (unix386.s <-- dsectrm2.s)
  2279                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2280                              <1> 
  2281                              <1> ; 10/12/2014
  2282                              <1> ;
  2283                              <1> ;int40h:
  2284                              <1> ;	pushf
  2285                              <1> ;	push 	cs
  2286                              <1> ;	;cli
  2287                              <1> ;	call 	DISKETTE_IO_1
  2288                              <1> ;	retn
  2289                              <1> 
  2290                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2291                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2292                              <1> ;
  2293                              <1> 
  2294                              <1> ;-- INT13H ---------------------------------------------------------------------
  2295                              <1> ; DISKETTE I/O
  2296                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2297                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2298                              <1> ; INPUT
  2299                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2300                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2301                              <1> ;		ON ALL DRIVES
  2302                              <1> ;------------------------------------------------------------------------------- 
  2303                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2304                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2305                              <1> ;-------------------------------------------------------------------------------
  2306                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2307                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2308                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2309                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2310                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2311                              <1> ;		320/360	320/360	    0-39
  2312                              <1> ;		320/360	1.2M	    0-39
  2313                              <1> ;		1.2M	1.2M	    0-79
  2314                              <1> ;		720K	720K	    0-79
  2315                              <1> ;		1.44M	1.44M	    0-79	
  2316                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2317                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2318                              <1> ;		320/360	320/360	     1-8/9
  2319                              <1> ;		320/360	1.2M	     1-8/9
  2320                              <1> ;		1.2M	1.2M	     1-15
  2321                              <1> ;		720K	720K	     1-9
  2322                              <1> ;		1.44M	1.44M	     1-18		
  2323                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2324                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2325                              <1> ;		320/360	320/360	        8/9
  2326                              <1> ;		320/360	1.2M	        8/9
  2327                              <1> ;		1.2M	1.2M		15
  2328                              <1> ;		720K	720K		9
  2329                              <1> ;		1.44M	1.44M		18
  2330                              <1> ;
  2331                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2332                              <1> ;
  2333                              <1> ;-------------------------------------------------------------------------------
  2334                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2335                              <1> ;-------------------------------------------------------------------------------
  2336                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2337                              <1> ;-------------------------------------------------------------------------------
  2338                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2339                              <1> ;-------------------------------------------------------------------------------
  2340                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2341                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2342                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2343                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2344                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2345                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2346                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2347                              <1> ;		READ/WRITE ACCESS.
  2348                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2349                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2350                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2351                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2352                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2353                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2354                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2355                              <1> ;
  2356                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2357                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2358                              <1> ;		---------------------------------------------
  2359                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2360                              <1> ;		---------------------------------------------
  2361                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2362                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2363                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2364                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2365                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2366                              <1> ;		---------------------------------------------
  2367                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2368                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2369                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2370                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2371                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2372                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2373                              <1> ;-------------------------------------------------------------------------------
  2374                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2375                              <1> ;	REGISTERS
  2376                              <1> ;	  INPUT
  2377                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2378                              <1> ;	  OUTPUT
  2379                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2380                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2381                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2382                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2383                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2384                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2385                              <1> ;	    (BH) - 0
  2386                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2387                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2388                              <1> ;	    (AX) - 0
  2389                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2390                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2391                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2392                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2393                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2394                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2395                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2396                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2397                              <1> ;-------------------------------------------------------------------------------
  2398                              <1> ;	(AH)= 15H  READ DASD TYPE
  2399                              <1> ;	OUTPUT REGISTERS
  2400                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2401                              <1> ;		00 - DRIVE NOT PRESENT	
  2402                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2403                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2404                              <1> ;		03 - RESERVED (FIXED DISK)
  2405                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2406                              <1> ;-------------------------------------------------------------------------------
  2407                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2408                              <1> ;	OUTPUT REGISTERS
  2409                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2410                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2411                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2412                              <1> ;-------------------------------------------------------------------------------
  2413                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2414                              <1> ;	INPUT REGISTERS
  2415                              <1> ;	(AL) -	00 - NOT USED	
  2416                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2417                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2418                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2419                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2420                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2421                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2422                              <1> ;-------------------------------------------------------------------------------
  2423                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2424                              <1> ;	INPUT REGISTERS
  2425                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2426                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2427                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2428                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2429                              <1> ;	OUTPUT REGISTERS:
  2430                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2431                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2432                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2433                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2434                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2435                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2436                              <1> ;-------------------------------------------------------------------------------
  2437                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2438                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2439                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2440                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2441                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2442                              <1> ;		CHANGE ERROR CODE
  2443                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2444                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2445                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2446                              <1> ;
  2447                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2448                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2449                              <1> ;-------------------------------------------------------------------------------
  2450                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2451                              <1> ;	AH = STATUS OF OPERATION
  2452                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2453                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2454                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2455                              <1> ;		TYPE AH=(15)).
  2456                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2457                              <1> ;	FOR READ/WRITE/VERIFY
  2458                              <1> ;		DS,BX,DX,CX PRESERVED
  2459                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2460                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2461                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2462                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2463                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2464                              <1> ;-------------------------------------------------------------------------------
  2465                              <1> ;
  2466                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2467                              <1> ;
  2468                              <1> ;   -----------------------------------------------------------------
  2469                              <1> ;   |       |       |       |       |       |       |       |       |
  2470                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2471                              <1> ;   |       |       |       |       |       |       |       |       |
  2472                              <1> ;   -----------------------------------------------------------------
  2473                              <1> ;	|	|	|	|	|	|	|	|
  2474                              <1> ;	|	|	|	|	|	-----------------
  2475                              <1> ;	|	|	|	|	|		|
  2476                              <1> ;	|	|	|	|    RESERVED		|
  2477                              <1> ;	|	|	|	|		  PRESENT STATE
  2478                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2479                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2480                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2481                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2482                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2483                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2484                              <1> ;	|	|	|	|	110: RESERVED
  2485                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2486                              <1> ;	|	|	|	|
  2487                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2488                              <1> ;	|	|	|
  2489                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2490                              <1> ;	|	|			DRIVE)
  2491                              <1> ;	|	|
  2492                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2493                              <1> ;
  2494                              <1> ;						00: 500 KBS
  2495                              <1> ;						01: 300 KBS
  2496                              <1> ;						10: 250 KBS
  2497                              <1> ;						11: RESERVED
  2498                              <1> ;
  2499                              <1> ;
  2500                              <1> ;-------------------------------------------------------------------------------
  2501                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2502                              <1> ;-------------------------------------------------------------------------------
  2503                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2504                              <1> ;-------------------------------------------------------------------------------
  2505                              <1> 
  2506                              <1> struc MD
  2507 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2508 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2509 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2510 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2511 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2512 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2513 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2514 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2515 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2516 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2517 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2518 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2519 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2520                              <1> endstruc
  2521                              <1> 
  2522                              <1> BIT7OFF	EQU	7FH
  2523                              <1> BIT7ON	EQU	80H
  2524                              <1> 
  2525                              <1> ;;int13h: ; 16/02/2015
  2526                              <1> ;; 16/02/2015 - 21/02/2015
  2527                              <1> int40h:
  2528 0000175C 9C                  <1> 	pushfd
  2529 0000175D 0E                  <1> 	push 	cs
  2530 0000175E E801000000          <1> 	call 	DISKETTE_IO_1
  2531 00001763 C3                  <1> 	retn	
  2532                              <1> 
  2533                              <1> DISKETTE_IO_1:
  2534                              <1> 
  2535 00001764 FB                  <1> 	STI				; INTERRUPTS BACK ON
  2536 00001765 55                  <1> 	PUSH	eBP			; USER REGISTER
  2537 00001766 57                  <1> 	PUSH	eDI			; USER REGISTER
  2538 00001767 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2539 00001768 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2540 00001769 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2541 0000176A 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2542                              <1> 					; [BP]   = SECTOR #
  2543                              <1> 					; [BP+1] = TRACK #
  2544                              <1> 					; [BP+2] = BUFFER OFFSET
  2545                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2546                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2547                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2548                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2549                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2550                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2551                              <1> 					; BH/[BP+3] = 0
  2552                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2553                              <1> 					; DH/[BP+5] = MAX HEAD #
  2554                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2555 0000176C 06                  <1> 	push	es ; 06/02/2015	
  2556 0000176D 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2557 0000176E 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2558                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2559                              <1> 	;mov	cx, cs
  2560                              <1> 	;mov	ds, cx
  2561 0000176F 66B91000            <1> 	mov	cx, KDATA
  2562 00001773 8ED9                <1>         mov     ds, cx
  2563 00001775 8EC1                <1>         mov     es, cx
  2564                              <1> 
  2565                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2566 00001777 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2567 0000177A 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2568 0000177C B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2569                              <1> OK_FUNC:
  2570 0000177E 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2571 00001781 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2572 00001783 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2573 00001786 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2574 00001788 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2575 0000178B 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2576 0000178D B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2577                              <1> OK_DRV:
  2578 0000178F 31C9                <1> 	xor	ecx, ecx
  2579                              <1> 	;mov	esi, ecx ; 08/02/2015
  2580                              <1> 	; 24/12/2021
  2581 00001791 89CE                <1> 	mov	esi, ecx
  2582 00001793 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2583 00001795 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2584                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2585                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2586 00001797 C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2587 0000179A BB[D2170000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2588 0000179F 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2589 000017A1 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2590 000017A3 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2591 000017A5 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2592 000017A8 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2593                              <1> 	;
  2594                              <1> 	; 11/12/2014
  2595 000017AB 8815[71660000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2596                              <1> 	;
  2597 000017B1 8A25[0C6C0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2598 000017B7 C605[0C6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2599                              <1> 
  2600                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2601                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2602                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2603                              <1> ;
  2604                              <1> ;		DI	: DRIVE #
  2605                              <1> ;		SI-HI	: HEAD #
  2606                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2607                              <1> ;		ES	: BUFFER SEGMENT
  2608                              <1> ;		[BP]	: SECTOR #
  2609                              <1> ;		[BP+1]	: TRACK #
  2610                              <1> ;		[BP+2]	: BUFFER OFFSET
  2611                              <1> ;
  2612                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2613                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2614                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2615                              <1> ;	SPECIFIC ERROR CODE.
  2616                              <1> ;
  2617                              <1> 					; (AH) = @DSKETTE_STATUS
  2618 000017BE FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2619 000017C0 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2620 000017C1 1F                  <1> 	POP	DS
  2621 000017C2 07                  <1> 	pop	es	; 06/02/2015
  2622 000017C3 59                  <1> 	POP	eCX
  2623 000017C4 5B                  <1> 	POP	eBX
  2624 000017C5 5A                  <1> 	POP	eDX
  2625 000017C6 5F                  <1> 	POP	eDI
  2626 000017C7 89E5                <1> 	MOV	eBP, eSP
  2627 000017C9 50                  <1> 	PUSH	eAX
  2628 000017CA 9C                  <1> 	PUSHFd
  2629 000017CB 58                  <1> 	POP	eAX
  2630                              <1> 	;MOV	[BP+6], AX
  2631 000017CC 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2632 000017CF 58                  <1> 	POP	eAX
  2633 000017D0 5D                  <1> 	POP	eBP
  2634 000017D1 CF                  <1> 	IRETd
  2635                              <1> 
  2636                              <1> ;-------------------------------------------------------------------------------
  2637                              <1> ; DW --> dd (06/02/2015)
  2638 000017D2 [36180000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2639 000017D6 [AB180000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2640 000017DA [BB180000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2641 000017DE [CC180000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2642 000017E2 [DD180000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2643 000017E6 [EE180000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2644 000017EA [72190000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2645 000017EE [72190000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2646 000017F2 [7E190000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2647 000017F6 [72190000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2648 000017FA [72190000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2649 000017FE [72190000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2650 00001802 [72190000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2651 00001806 [72190000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2652 0000180A [72190000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2653 0000180E [72190000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2654 00001812 [72190000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2655 00001816 [72190000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2656 0000181A [72190000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2657 0000181E [72190000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2658 00001822 [72190000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2659 00001826 [3D1A0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2660 0000182A [651A0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2661 0000182E [9E1A0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2662 00001832 [1F1B0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2663                              <1> FNC_TAE EQU     $                       ; END
  2664                              <1> 
  2665                              <1> ;-------------------------------------------------------------------------------
  2666                              <1> ; DISK_RESET	(AH = 00H)	
  2667                              <1> ;		RESET THE DISKETTE SYSTEM.
  2668                              <1> ;
  2669                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2670                              <1> ;-------------------------------------------------------------------------------
  2671                              <1> DSK_RESET:
  2672 00001836 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2673 0000183A FA                  <1> 	CLI				; NO INTERRUPTS
  2674 0000183B A0[0A6C0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2675 00001840 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2676 00001842 C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2677                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2678 00001845 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2679 00001847 EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2680 00001848 C605[096C0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2681                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2682                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2683                              <1> 					;      PULSE WIDTH)
  2684                              <1> 	; 19/12/2014
  2685                              <1> 	NEWIODELAY
  2158 0000184F E6EB                <2>  out 0EBh,al
  2686                              <1> 
  2687                              <1> 	; 17/12/2014 
  2688                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2689 00001851 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2690                              <1> wdw1:
  2691                              <1> 	NEWIODELAY   ; 27/02/2015
  2158 00001856 E6EB                <2>  out 0EBh,al
  2692 00001858 E2FC                <1> 	loop	wdw1
  2693                              <1> 	;
  2694 0000185A 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2695 0000185C EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2696                              <1> 	; 16/12/2014
  2697                              <1> 	IODELAY
  2153 0000185D EB00                <2>  jmp short $+2
  2154 0000185F EB00                <2>  jmp short $+2
  2698                              <1> 	;
  2699                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2700 00001861 E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2701 00001866 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2702 00001868 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2703                              <1> NXT_DRV:
  2704                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2705                              <1> 	; 24/12/2021
  2706 0000186C 51                  <1> 	push	ecx
  2707 0000186D B8[A1180000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2708 00001872 50                  <1> 	PUSH	eAX			; "
  2709 00001873 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2710 00001875 E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2711 0000187A 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2712 0000187B E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2713                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2714                              <1> 	; 24/12/2021
  2715 00001880 59                  <1> 	pop	ecx
  2716 00001881 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2717 00001883 3A0D[0D6C0000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2718 00001889 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2719 0000188B FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2720 0000188D 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2721 00001890 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2722                              <1> 	;
  2723 00001892 E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2724                              <1> RESBAC:
  2725 00001897 E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2726                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2727                              <1> 	; 24/12/2021
  2728 0000189C 89F3                <1> 	mov	ebx, esi
  2729 0000189E 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2730 000018A0 C3                  <1> 	RETn		
  2731                              <1> DR_POP_ERR:
  2732                              <1> 	;POP	CX			; CLEAR STACK
  2733                              <1> 	; 24/12/2021
  2734 000018A1 59                  <1> 	pop	ecx
  2735                              <1> DR_ERR:
  2736 000018A2 800D[0C6C0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2737 000018A9 EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2738                              <1> 
  2739                              <1> ;-------------------------------------------------------------------------------
  2740                              <1> ; DISK_STATUS	(AH = 01H)
  2741                              <1> ;	DISKETTE STATUS.
  2742                              <1> ;
  2743                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2744                              <1> ;
  2745                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2746                              <1> ;-------------------------------------------------------------------------------
  2747                              <1> DSK_STATUS:
  2748 000018AB 8825[0C6C0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2749 000018B1 E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2750                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2751                              <1> 	; 24/12/2021
  2752 000018B6 89F3                <1> 	mov	ebx, esi
  2753 000018B8 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2754 000018BA C3                  <1> 	RETn		
  2755                              <1> 
  2756                              <1> ;-------------------------------------------------------------------------------
  2757                              <1> ; DISK_READ	(AH = 02H)	
  2758                              <1> ;	DISKETTE READ.
  2759                              <1> ;
  2760                              <1> ; ON ENTRY:	DI	: DRIVE #
  2761                              <1> ;		SI-HI	: HEAD #
  2762                              <1> ;		SI-LOW	: # OF SECTORS
  2763                              <1> ;		ES	: BUFFER SEGMENT
  2764                              <1> ;		[BP]	: SECTOR #
  2765                              <1> ;		[BP+1]	: TRACK #
  2766                              <1> ;		[BP+2]	: BUFFER OFFSET
  2767                              <1> ;
  2768                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2769                              <1> ;-------------------------------------------------------------------------------
  2770                              <1> 
  2771                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2772                              <1> 
  2773                              <1> DSK_READ:
  2774 000018BB 8025[0A6C0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2775 000018C2 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2776 000018C6 E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2777 000018CB C3                  <1> 	RETn
  2778                              <1> 
  2779                              <1> ;-------------------------------------------------------------------------------
  2780                              <1> ; DISK_WRITE	(AH = 03H)
  2781                              <1> ;	DISKETTE WRITE.
  2782                              <1> ;
  2783                              <1> ; ON ENTRY:	DI	: DRIVE #
  2784                              <1> ;		SI-HI	: HEAD #
  2785                              <1> ;		SI-LOW	: # OF SECTORS
  2786                              <1> ;		ES	: BUFFER SEGMENT
  2787                              <1> ;		[BP]	: SECTOR #
  2788                              <1> ;		[BP+1]	: TRACK #
  2789                              <1> ;		[BP+2]	: BUFFER OFFSET
  2790                              <1> ;
  2791                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2792                              <1> ;-------------------------------------------------------------------------------
  2793                              <1> 
  2794                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2795                              <1> 
  2796                              <1> DSK_WRITE:
  2797 000018CC 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2798 000018D0 800D[0A6C0000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2799 000018D7 E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2800 000018DC C3                  <1> 	RETn
  2801                              <1> 
  2802                              <1> ;-------------------------------------------------------------------------------
  2803                              <1> ; DISK_VERF	(AH = 04H)
  2804                              <1> ;	DISKETTE VERIFY.
  2805                              <1> ;
  2806                              <1> ; ON ENTRY:	DI	: DRIVE #
  2807                              <1> ;		SI-HI	: HEAD #
  2808                              <1> ;		SI-LOW	: # OF SECTORS
  2809                              <1> ;		ES	: BUFFER SEGMENT
  2810                              <1> ;		[BP]	: SECTOR #
  2811                              <1> ;		[BP+1]	: TRACK #
  2812                              <1> ;		[BP+2]	: BUFFER OFFSET
  2813                              <1> ;
  2814                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2815                              <1> ;-------------------------------------------------------------------------------
  2816                              <1> DSK_VERF:
  2817 000018DD 8025[0A6C0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2818 000018E4 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2819 000018E8 E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2820 000018ED C3                  <1> 	RETn
  2821                              <1> 
  2822                              <1> ;-------------------------------------------------------------------------------
  2823                              <1> ; DISK_FORMAT	(AH = 05H)
  2824                              <1> ;	DISKETTE FORMAT.
  2825                              <1> ;
  2826                              <1> ; ON ENTRY:	DI	: DRIVE #
  2827                              <1> ;		SI-HI	: HEAD #
  2828                              <1> ;		SI-LOW	: # OF SECTORS
  2829                              <1> ;		ES	: BUFFER SEGMENT
  2830                              <1> ;		[BP]	: SECTOR #
  2831                              <1> ;		[BP+1]	: TRACK #
  2832                              <1> ;		[BP+2]	: BUFFER OFFSET
  2833                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2834                              <1> ;
  2835                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2836                              <1> ;-------------------------------------------------------------------------------
  2837                              <1> DSK_FORMAT:
  2838 000018EE E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2839 000018F3 E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2840 000018F8 800D[0A6C0000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2841 000018FF E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2842 00001904 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2843 00001906 E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2844 0000190B E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2845 00001910 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2846 00001912 E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2847                              <1> FM_WR:
  2848 00001917 E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2849 0000191C 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2850 0000191E B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2851 00001920 E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2852 00001925 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2853 00001927 B8[63190000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2854 0000192C 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2855 0000192D B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2856 0000192F E80E090000          <1> 	CALL	GET_PARM
  2857 00001934 E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2858 00001939 B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2859 0000193B E802090000          <1> 	CALL	GET_PARM
  2860 00001940 E8030A0000          <1> 	CALL	NEC_OUTPUT
  2861 00001945 B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2862 00001947 E8F6080000          <1> 	CALL	GET_PARM
  2863 0000194C E8F7090000          <1> 	CALL	NEC_OUTPUT
  2864 00001951 B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2865 00001953 E8EA080000          <1> 	CALL	GET_PARM
  2866 00001958 E8EB090000          <1> 	CALL	NEC_OUTPUT
  2867 0000195D 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2868 0000195E E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2869                              <1> FM_DON:
  2870 00001963 E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2871 00001968 E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2872                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2873 0000196D 89F3                <1> 	mov	ebx, esi ; 24/12/2021
  2874 0000196F 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2875 00001971 C3                  <1> 	RETn
  2876                              <1> 
  2877                              <1> ;-------------------------------------------------------------------------------
  2878                              <1> ; FNC_ERR
  2879                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2880                              <1> ;	SET BAD COMMAND IN STATUS.
  2881                              <1> ;
  2882                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2883                              <1> ;-------------------------------------------------------------------------------
  2884                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2885                              <1> 	;MOV	AX,SI			; RESTORE AL
  2886                              <1> 	; 24/12/2021
  2887 00001972 89F0                <1> 	mov	eax, esi
  2888 00001974 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2889 00001976 8825[0C6C0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2890 0000197C F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2891 0000197D C3                  <1> 	RETn
  2892                              <1> 
  2893                              <1> ;-------------------------------------------------------------------------------
  2894                              <1> ; DISK_PARMS	(AH = 08H)	
  2895                              <1> ;	READ DRIVE PARAMETERS.
  2896                              <1> ;
  2897                              <1> ; ON ENTRY:	DI : DRIVE #
  2898                              <1> ;
  2899                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2900                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2901                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2902                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2903                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2904                              <1> ;		BH/[BP+3] = 0
  2905                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2906                              <1> ;		DH/[BP+5] = MAX HEAD #
  2907                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2908                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2909                              <1> ;		AX        = 0
  2910                              <1> ;
  2911                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2912                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2913                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2914                              <1> ;		       CALLER.
  2915                              <1> ;-------------------------------------------------------------------------------
  2916                              <1> DSK_PARMS:
  2917 0000197E E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2918                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2919 00001983 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2920 00001985 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2921                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2922                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2923                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2924                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2925                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2926                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2927                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2928                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2929                              <1> 	;sub	edx, edx
  2930 00001988 66A1[7E660000]      <1> 	mov     ax, [fd0_type]
  2931 0000198E 6621C0              <1> 	and     ax, ax
  2932 00001991 7473                <1> 	jz      short NON_DRV
  2933 00001993 FEC2                <1> 	inc     dl
  2934 00001995 20E4                <1> 	and     ah, ah
  2935 00001997 7402                <1> 	jz      short STO_DL
  2936 00001999 FEC2                <1> 	inc     dl
  2937                              <1> STO_DL:
  2938                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2939 0000199B 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2940 0000199E 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2941 000019A2 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2942                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2943 000019A4 C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2944 000019A8 E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2945                              <1> 	;;20/02/2015
  2946                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2947                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2948 000019AD 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2949 000019AF E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2950 000019B4 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2951                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2952 000019B6 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2953 000019B9 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2954 000019BC 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2955 000019BF EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2956                              <1> CHK_EST:
  2957 000019C1 8AA7[196C0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2958 000019C7 F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2959 000019CA 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2960                              <1> USE_EST:
  2961 000019CC 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2962 000019CF 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2963 000019D2 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2964                              <1> 
  2965                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2966                              <1> 
  2967 000019D4 B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2968 000019D6 E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2969 000019DB 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2970 000019DE 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2971 000019E1 F687[196C0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2972 000019E8 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2973                              <1> 
  2974                              <1> ;-----	IT IS 1.44 MB DRIVE
  2975                              <1> 
  2976                              <1> PARM144:
  2977 000019EA B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2978 000019EC E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2979 000019F1 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2980 000019F4 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2981                              <1> STO_CX:
  2982 000019F7 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2983                              <1> ES_DI:
  2984                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2985 000019FA 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2986                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2987                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2988                              <1> DP_OUT:
  2989 000019FD E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2990                              <1> 	;XOR	AX,AX			; CLEAR
  2991                              <1> 	; 24/12/2021
  2992 00001A02 31C0                <1> 	xor	eax, eax
  2993 00001A04 F8                  <1> 	CLC
  2994 00001A05 C3                  <1> 	RETn
  2995                              <1> 
  2996                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2997                              <1> 
  2998                              <1> NON_DRV:
  2999                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  3000 00001A06 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  3001                              <1> NON_DRV1:
  3002 00001A09 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  3003 00001A0E 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  3004                              <1> 
  3005                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  3006                              <1> 	
  3007 00001A10 E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  3008                              <1> 	;MOV	AX,SI			; RESTORE AL
  3009 00001A15 89F0                <1> 	mov	eax, esi ; 24/12/2021
  3010 00001A17 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  3011 00001A19 F9                  <1> 	STC
  3012 00001A1A C3                  <1> 	RETn
  3013                              <1> 
  3014                              <1> NON_DRV2:
  3015                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  3016 00001A1B 31C0                <1> 	xor	eax, eax	
  3017 00001A1D 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  3018                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  3019 00001A21 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  3020                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  3021 00001A24 89450C              <1> 	mov	[ebp+12], eax
  3022                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  3023 00001A27 EBD4                <1> 	JMP	SHORT DP_OUT
  3024                              <1> 
  3025                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  3026                              <1> 
  3027                              <1> USE_EST2:
  3028 00001A29 B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  3029 00001A2B E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3030 00001A30 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3031 00001A33 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  3032 00001A36 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3033 00001A39 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  3034 00001A3B EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  3035                              <1> 
  3036                              <1> ;-------------------------------------------------------------------------------
  3037                              <1> ; DISK_TYPE (AH = 15H)	
  3038                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  3039                              <1> ;
  3040                              <1> ;  ON ENTRY:	DI = DRIVE #
  3041                              <1> ;
  3042                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  3043                              <1> ;-------------------------------------------------------------------------------
  3044                              <1> DSK_TYPE:
  3045 00001A3D E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3046 00001A42 8A87[196C0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  3047 00001A48 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  3048 00001A4A 7415                <1> 	JZ	short NO_DRV
  3049 00001A4C B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  3050 00001A4E A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  3051 00001A50 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  3052 00001A52 B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  3053                              <1> DT_BACK:
  3054                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  3055 00001A54 50                  <1> 	push	eax ; 24/12/2021
  3056 00001A55 E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3057                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  3058 00001A5A 58                  <1> 	pop	eax ; 24/12/2021
  3059 00001A5B F8                  <1> 	CLC				; NO ERROR
  3060                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3061                              <1> 	; 24/12/2021
  3062 00001A5C 89F3                <1> 	mov	ebx, esi
  3063 00001A5E 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3064 00001A60 C3                  <1> 	RETn
  3065                              <1> NO_DRV:	
  3066 00001A61 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  3067 00001A63 EBEF                <1> 	JMP	SHORT DT_BACK
  3068                              <1> 
  3069                              <1> ;-------------------------------------------------------------------------------
  3070                              <1> ; DISK_CHANGE	(AH = 16H)
  3071                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  3072                              <1> ;
  3073                              <1> ; ON ENTRY:	DI = DRIVE #
  3074                              <1> ;
  3075                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  3076                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  3077                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  3078                              <1> ;-------------------------------------------------------------------------------
  3079                              <1> DSK_CHANGE:
  3080 00001A65 E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3081 00001A6A 8A87[196C0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  3082 00001A70 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  3083 00001A72 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  3084 00001A74 A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  3085 00001A76 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  3086                              <1> DC0:
  3087 00001A78 E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  3088 00001A7D 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  3089                              <1> 
  3090 00001A7F C605[0C6C0000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  3091                              <1> 
  3092 00001A86 E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3093 00001A8B E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3094                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3095                              <1> 	; 24/12/2021
  3096 00001A90 89F3                <1> 	mov	ebx, esi
  3097 00001A92 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3098 00001A94 C3                  <1> 	RETn
  3099                              <1> DC_NON:
  3100 00001A95 800D[0C6C0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  3101 00001A9C EBE8                <1> 	JMP	SHORT FINIS
  3102                              <1> 
  3103                              <1> ;-------------------------------------------------------------------------------
  3104                              <1> ; FORMAT_SET	(AH = 17H)
  3105                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  3106                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  3107                              <1> ;
  3108                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3109                              <1> ;		DI     = DRIVE #
  3110                              <1> ;
  3111                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3112                              <1> ;		AH = @DSKETTE_STATUS
  3113                              <1> ;		CY = 1 IF ERROR
  3114                              <1> ;-------------------------------------------------------------------------------
  3115                              <1> FORMAT_SET:
  3116 00001A9E E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3117                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3118                              <1> 	; 24/12/2021
  3119 00001AA3 56                  <1> 	push	esi
  3120 00001AA4 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3121 00001AA7 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3122 00001AA9 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3123 00001AAC 80A7[196C0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3124 00001AB3 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3125 00001AB5 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3126 00001AB7 808F[196C0000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3127 00001ABE EB48                <1> 	JMP	SHORT S0
  3128                              <1> NOT_320:
  3129 00001AC0 E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3130 00001AC5 803D[0C6C0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3131 00001ACC 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3132                              <1> S3:
  3133 00001ACE 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3134 00001AD0 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3135 00001AD2 808F[196C0000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3136 00001AD9 EB2D                <1> 	JMP	SHORT S0
  3137                              <1> NOT_320_12:
  3138 00001ADB 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3139 00001ADD 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3140 00001ADF 808F[196C0000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3141 00001AE6 EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3142                              <1> NOT_12:	
  3143 00001AE8 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3144 00001AEA 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3145                              <1> 
  3146 00001AEC F687[196C0000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3147 00001AF3 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3148 00001AF5 B050                <1> 	MOV	AL,MED_DET+RATE_300
  3149 00001AF7 F687[196C0000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3150 00001AFE 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3151                              <1> ASSUME:
  3152 00001B00 B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3153                              <1> OR_IT_IN:
  3154 00001B02 0887[196C0000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3155                              <1> S0:
  3156 00001B08 E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3157 00001B0D E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3158                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3159                              <1> 	; 24/12/2021
  3160 00001B12 5B                  <1> 	pop	ebx
  3161 00001B13 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3162 00001B15 C3                  <1> 	RETn
  3163                              <1> FS_ERR:
  3164 00001B16 C605[0C6C0000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3165 00001B1D EBE9                <1> 	JMP	SHORT S0
  3166                              <1> 
  3167                              <1> ;-------------------------------------------------------------------------------
  3168                              <1> ; SET_MEDIA	(AH = 18H)
  3169                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3170                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3171                              <1> ;
  3172                              <1> ; ON ENTRY:
  3173                              <1> ;	[BP]	= SECTOR PER TRACK
  3174                              <1> ;	[BP+1]	= TRACK #
  3175                              <1> ;	DI	= DRIVE #
  3176                              <1> ;
  3177                              <1> ; ON EXIT:
  3178                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3179                              <1> ;	IF NO ERROR:
  3180                              <1> ;		AH = 0
  3181                              <1> ;		CY = 0
  3182                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3183                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3184                              <1> ;	IF ERROR:	
  3185                              <1> ;		AH = @DSKETTE_STATUS
  3186                              <1> ;		CY = 1
  3187                              <1> ;-------------------------------------------------------------------------------
  3188                              <1> SET_MEDIA:
  3189 00001B1F E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3190 00001B24 F687[196C0000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3191 00001B2B 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3192 00001B2D E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3193 00001B32 803D[0C6C0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3194 00001B39 746B                <1> 	JE	short SM_RTN
  3195 00001B3B C605[0C6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3196                              <1> SM_CMOS:
  3197 00001B42 E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3198                              <1> 	;;20/02/2015
  3199                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3200                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3201 00001B47 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3202 00001B49 E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3203 00001B4E 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3204 00001B50 57                  <1> 	PUSH	eDI			; SAVE REG.
  3205 00001B51 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3206 00001B53 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3207                              <1> DR_SEARCH:
  3208 00001B58 8AA3[FC650000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3209 00001B5E 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3210 00001B61 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3211 00001B63 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3212                              <1> DR_FND:
  3213 00001B65 8BBB[FD650000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3214                              <1> MD_SEARCH:
  3215 00001B6B 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3216 00001B6E 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3217 00001B71 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3218 00001B73 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3219 00001B76 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3220 00001B79 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3221                              <1> NXT_MD:
  3222                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3223 00001B7B 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3224 00001B7E E2D8                <1> 	LOOP    DR_SEARCH
  3225 00001B80 5F                  <1> 	POP	eDI			; RESTORE REG.
  3226                              <1> MD_NOT_FND:
  3227 00001B81 C605[0C6C0000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3228 00001B88 EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3229                              <1> MD_FND:
  3230 00001B8A 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3231 00001B8D 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3232 00001B8F 7502                <1> 	JNE	short MD_SET
  3233 00001B91 0C20                <1> 	OR	AL,DBL_STEP
  3234                              <1> MD_SET:
  3235                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3236 00001B93 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3237 00001B96 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3238 00001B98 5F                  <1> 	POP	eDI
  3239 00001B99 80A7[196C0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3240 00001BA0 0887[196C0000]      <1> 	OR	[DSK_STATE+eDI], AL
  3241                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3242                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3243                              <1> SM_RTN:
  3244 00001BA6 E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3245 00001BAB E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3246 00001BB0 C3                  <1> 	RETn
  3247                              <1> 
  3248                              <1> ;----------------------------------------------------------------
  3249                              <1> ; DR_TYPE_CHECK							:
  3250                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3251                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3252                              <1> ; ON ENTRY:							:
  3253                              <1> ;	AL = DRIVE TYPE						:
  3254                              <1> ; ON EXIT:							:
  3255                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3256                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3257                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3258                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3259                              <1> ; REGISTERS ALTERED: eBX						:
  3260                              <1> ;----------------------------------------------------------------		
  3261                              <1> DR_TYPE_CHECK:
  3262                              <1> 	;PUSH	AX			
  3263                              <1> 	; 24/12/2021
  3264 00001BB1 50                  <1> 	push	eax
  3265 00001BB2 51                  <1> 	PUSH	eCX
  3266 00001BB3 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3267 00001BB5 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3268                              <1> TYPE_CHK:	
  3269 00001BBA 8AA3[FC650000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3270 00001BC0 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3271 00001BC2 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3272                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3273 00001BC4 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3274 00001BC7 E2F1                <1> 	LOOP    TYPE_CHK
  3275                              <1> 	;
  3276 00001BC9 BB[5B660000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3277                              <1> 					; Default for GET_PARM (11/12/2014)
  3278                              <1> 	;
  3279 00001BCE F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3280 00001BCF EB06                <1> 	JMP	SHORT TYPE_RTN
  3281                              <1> DR_TYPE_VALID:
  3282 00001BD1 8B9B[FD650000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3283                              <1> TYPE_RTN:
  3284 00001BD7 59                  <1> 	POP	eCX
  3285                              <1> 	;POP	AX
  3286                              <1> 	; 24/12/2021
  3287 00001BD8 58                  <1> 	pop	eax
  3288 00001BD9 C3                  <1> 	RETn	
  3289                              <1> 		
  3290                              <1> ;----------------------------------------------------------------
  3291                              <1> ; SEND_SPEC							:
  3292                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3293                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3294                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3295                              <1> ; ON EXIT:	NONE						:	
  3296                              <1> ; REGISTERS ALTERED: CX, DX					:
  3297                              <1> ;----------------------------------------------------------------		
  3298                              <1> SEND_SPEC:
  3299 00001BDA 50                  <1> 	PUSH	eAX			; SAVE AX
  3300 00001BDB B8[011C0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3301 00001BE0 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3302 00001BE1 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3303 00001BE3 E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3304 00001BE8 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3305 00001BEA E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3306 00001BEF E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3307 00001BF4 B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3308 00001BF6 E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3309 00001BFB E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3310 00001C00 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3311                              <1> SPECBAC:
  3312 00001C01 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3313 00001C02 C3                  <1> 	RETn
  3314                              <1> 
  3315                              <1> ;----------------------------------------------------------------
  3316                              <1> ; SEND_SPEC_MD							:
  3317                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3318                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3319                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3320                              <1> ; ON EXIT:	NONE						:	
  3321                              <1> ; REGISTERS ALTERED: AX						:
  3322                              <1> ;----------------------------------------------------------------		
  3323                              <1> SEND_SPEC_MD:
  3324 00001C03 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3325 00001C04 B8[211C0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3326 00001C09 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3327 00001C0A B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3328 00001C0C E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3329 00001C11 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3330 00001C13 E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3331 00001C18 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3332 00001C1B E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3333 00001C20 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3334                              <1> SPEC_ESBAC:
  3335 00001C21 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3336 00001C22 C3                  <1> 	RETn
  3337                              <1> 
  3338                              <1> ;-------------------------------------------------------------------------------
  3339                              <1> ; XLAT_NEW  
  3340                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3341                              <1> ;	MODE TO NEW ARCHITECTURE.
  3342                              <1> ;
  3343                              <1> ; ON ENTRY:	DI = DRIVE #
  3344                              <1> ;-------------------------------------------------------------------------------
  3345                              <1> XLAT_NEW:
  3346 00001C23 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3347 00001C26 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3348 00001C28 80BF[196C0000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3349 00001C2F 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3350 00001C31 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3351 00001C34 C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3352 00001C37 A0[186C0000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3353 00001C3C D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3354 00001C3E 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3355 00001C40 80A7[196C0000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3356 00001C47 0887[196C0000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3357                              <1> XN_OUT:
  3358 00001C4D C3                  <1> 	RETn
  3359                              <1> DO_DET:
  3360 00001C4E E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3361 00001C53 C3                  <1> 	RETn
  3362                              <1> 
  3363                              <1> ;-------------------------------------------------------------------------------
  3364                              <1> ; XLAT_OLD 
  3365                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3366                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3367                              <1> ;
  3368                              <1> ; ON ENTRY:	DI = DRIVE
  3369                              <1> ;-------------------------------------------------------------------------------
  3370                              <1> XLAT_OLD:
  3371 00001C54 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3372                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3373                              <1>         ;ja	XO_OUT
  3374                              <1>         ; 24/12/2021
  3375 00001C57 77F4                <1> 	ja	short XN_OUT
  3376 00001C59 80BF[196C0000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3377 00001C60 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3378                              <1> 
  3379                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3380                              <1> 
  3381 00001C62 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3382 00001C65 C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3383 00001C68 B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3384 00001C6A D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3385 00001C6C 8425[186C0000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3386 00001C72 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3387                              <1> 
  3388                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3389                              <1> 
  3390 00001C74 B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3391 00001C76 D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3392 00001C78 F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3393 00001C7A 2025[186C0000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3394                              <1> 
  3395                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3396                              <1> 
  3397 00001C80 8A87[196C0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3398 00001C86 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3399 00001C88 D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3400 00001C8A 0805[186C0000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3401                              <1> 
  3402                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3403                              <1> 
  3404                              <1> SAVE_SET:
  3405 00001C90 8AA7[196C0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3406 00001C96 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3407 00001C98 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3408 00001C9B 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3409 00001C9E 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3410 00001CA0 B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3411 00001CA2 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3412 00001CA5 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3413 00001CA7 F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3414 00001CAA 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3415                              <1> UNKNO:
  3416 00001CAC B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3417 00001CAE EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3418                              <1> CHK_144:
  3419 00001CB0 E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3420                              <1> 	;;20/02/2015
  3421                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3422 00001CB5 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3423 00001CB7 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3424 00001CB9 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3425 00001CBB B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3426 00001CBD EB0C                <1> 	JMP	SHORT TST_DET
  3427                              <1> CHK_250:
  3428 00001CBF B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3429 00001CC1 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3430 00001CC4 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3431 00001CC6 F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3432 00001CC9 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3433                              <1> TST_DET:
  3434 00001CCB F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3435 00001CCE 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3436 00001CD0 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3437                              <1> AL_SET:
  3438 00001CD2 80A7[196C0000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3439 00001CD9 0887[196C0000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3440                              <1> XO_OUT:
  3441 00001CDF C3                  <1> 	RETn
  3442                              <1> 
  3443                              <1> ;-------------------------------------------------------------------------------
  3444                              <1> ; RD_WR_VF
  3445                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3446                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3447                              <1> ;
  3448                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3449                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3450                              <1> ;
  3451                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3452                              <1> ;-------------------------------------------------------------------------------
  3453                              <1> RD_WR_VF:
  3454                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3455 00001CE0 50                  <1> 	push	eax ; 24/12/2021
  3456 00001CE1 E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3457 00001CE6 E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3458                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3459 00001CEB 58                  <1> 	pop	eax ; 24/12/2021
  3460                              <1> DO_AGAIN:
  3461                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3462 00001CEC 50                  <1> 	push	eax ; 24/12/2021
  3463 00001CED E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3464                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3465 00001CF2 58                  <1> 	pop	eax ; 24/12/2021
  3466                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3467                              <1> 	; 24/12/2021
  3468 00001CF3 7305                <1> 	jnc	short RWV
  3469 00001CF5 E9C3000000          <1> 	jmp	RWV_END
  3470                              <1> RWV:
  3471                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3472 00001CFA 50                  <1> 	push	eax ; 24/12/2021
  3473 00001CFB 8AB7[196C0000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3474 00001D01 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3475 00001D04 E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3476                              <1> 	;;20/02/2015
  3477                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3478 00001D09 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3479 00001D0B 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3480 00001D0D 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3481 00001D0F F687[196C0000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3482 00001D16 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3483 00001D18 B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3484 00001D1A EB0F                <1> 	JMP	SHORT RWV_2
  3485                              <1> RWV_1:
  3486 00001D1C 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3487 00001D1E F687[196C0000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3488 00001D25 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3489 00001D27 B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3490 00001D29 EB04                <1> 	jmp	short rwv_3
  3491                              <1> RWV_2:
  3492 00001D2B 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3493 00001D2D 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3494                              <1> rwv_3:
  3495 00001D2F E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3496 00001D34 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3497                              <1> 
  3498                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3499                              <1> 
  3500 00001D36 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3501 00001D37 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3502 00001D39 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3503                              <1> RWV_DR_SEARCH:
  3504 00001D3E 8AA3[FC650000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3505 00001D44 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3506 00001D47 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3507 00001D49 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3508                              <1> RWV_DR_FND:
  3509 00001D4B 8BBB[FD650000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3510                              <1> RWV_MD_SEARH:
  3511 00001D51 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3512 00001D54 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3513                              <1> RWV_NXT_MD:
  3514                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3515 00001D56 83C305              <1> 	add	eBX, 5
  3516 00001D59 E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3517 00001D5B 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3518                              <1> 
  3519                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3520                              <1> 
  3521                              <1> RWV_ASSUME:
  3522 00001D5C BB[1A660000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3523 00001D61 F687[196C0000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3524 00001D68 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3525 00001D6A BB[34660000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3526 00001D6F EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3527                              <1> 
  3528                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3529                              <1> 	 			
  3530                              <1> RWV_MD_FND:
  3531 00001D71 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3532 00001D73 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3533                              <1> 	
  3534                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3535                              <1> 
  3536                              <1> RWV_MD_FND1:
  3537 00001D74 E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3538 00001D79 E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3539 00001D7E 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3540 00001D80 E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3541                              <1> RWV_DBL:
  3542 00001D85 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3543 00001D86 E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3544 00001D8B 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3545 00001D8C 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3546                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3547 00001D8E 58                  <1> 	pop	eax ; 24/12/2021
  3548                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3549 00001D8F 50                  <1> 	push	eax ; 24/12/2021
  3550 00001D90 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3551 00001D91 E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3552 00001D96 5B                  <1> 	POP	eBX 
  3553                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3554 00001D97 58                  <1> 	pop	eax ; 24/12/2021
  3555 00001D98 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3556                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3557 00001D9A 50                  <1> 	push	eax ; 24/12/2021
  3558 00001D9B 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3559 00001D9C E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3560 00001DA1 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3561 00001DA2 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3562 00001DA4 E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3563 00001DA9 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3564 00001DAB E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3565                              <1> CHK_RET:
  3566 00001DB0 E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3567                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3568 00001DB5 58                  <1> 	pop	eax ; 24/12/2021
  3569 00001DB6 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3570 00001DB8 E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3571                              <1> RWV_END:
  3572 00001DBD E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3573 00001DC2 E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3574                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3575                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3576 00001DC7 50                  <1> 	push	eax ; 24/12/2021
  3577 00001DC8 E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3578                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3579 00001DCD 58                  <1> 	pop	eax ; 24/12/2021
  3580 00001DCE E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3581 00001DD3 C3                  <1> 	RETn
  3582                              <1> 
  3583                              <1> ;-------------------------------------------------------------------------------
  3584                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3585                              <1> ;-------------------------------------------------------------------------------
  3586                              <1> SETUP_STATE:
  3587 00001DD4 F687[196C0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3588 00001DDB 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3589 00001DDD 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3590 00001DE1 F687[196C0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3591 00001DE8 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3592 00001DEA F687[196C0000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3593 00001DF1 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3594 00001DF3 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3595                              <1> AX_SET:	
  3596 00001DF7 80A7[196C0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3597 00001DFE 08A7[196C0000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3598 00001E04 8025[146C0000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3599 00001E0B C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3600 00001E0E 0805[146C0000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3601                              <1> J1C:	
  3602 00001E14 C3                  <1> 	RETn
  3603                              <1> 
  3604                              <1> ;-------------------------------------------------------------------------------
  3605                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3606                              <1> ;-------------------------------------------------------------------------------
  3607                              <1> FMT_INIT:
  3608 00001E15 F687[196C0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3609 00001E1C 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3610 00001E1E E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3611                              <1> 	;; 20/02/2015
  3612                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3613 00001E23 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3614 00001E25 FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3615                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3616 00001E27 8AA7[196C0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3617 00001E2D 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3618 00001E30 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3619 00001E32 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3620 00001E34 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3621 00001E37 EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3622                              <1> N_360:	
  3623 00001E39 FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3624 00001E3B 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3625                              <1> F1_RATE:
  3626 00001E3D 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3627 00001E40 EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3628                              <1> N_12:	
  3629 00001E42 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3630 00001E44 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3631 00001E46 F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3632 00001E49 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3633 00001E4B F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3634 00001E4E 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3635 00001E50 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3636 00001E53 EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3637                              <1> N_720:
  3638 00001E55 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3639 00001E57 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3640 00001E59 EBE2                <1> 	JMP	SHORT F1_RATE
  3641                              <1> ISNT_12: 
  3642 00001E5B 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3643                              <1> 
  3644                              <1> SKP_STATE:
  3645 00001E5E 88A7[196C0000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3646                              <1> F1_OUT:
  3647 00001E64 C3                  <1> 	RETn
  3648                              <1> CL_DRV:	
  3649 00001E65 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3650 00001E67 EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3651                              <1> 
  3652                              <1> ;-------------------------------------------------------------------------------
  3653                              <1> ; MED_CHANGE	
  3654                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3655                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3656                              <1> ;
  3657                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3658                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3659                              <1> ;-------------------------------------------------------------------------------
  3660                              <1> MED_CHANGE:
  3661 00001E69 E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3662 00001E6E 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3663 00001E70 80A7[196C0000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3664                              <1> 
  3665                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3666                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3667                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3668                              <1> 
  3669 00001E77 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3670 00001E7A B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3671 00001E7C D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3672 00001E7E F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3673 00001E80 FA                  <1> 	CLI				; NO INTERRUPTS
  3674 00001E81 2005[0A6C0000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3675 00001E87 FB                  <1> 	STI				; INTERRUPTS ENABLED
  3676 00001E88 E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3677                              <1> 
  3678                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3679                              <1> 
  3680 00001E8D E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3681 00001E92 B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3682 00001E94 E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3683 00001E99 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3684 00001E9B E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3685 00001EA0 C605[0C6C0000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3686                              <1> OK1:
  3687 00001EA7 E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3688 00001EAC 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3689                              <1> OK4:
  3690 00001EAE C605[0C6C0000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3691                              <1> OK2:		
  3692 00001EB5 F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3693 00001EB6 C3                  <1> 	RETn
  3694                              <1> MC_OUT:
  3695 00001EB7 F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3696 00001EB8 C3                  <1> 	RETn
  3697                              <1> 
  3698                              <1> ;-------------------------------------------------------------------------------
  3699                              <1> ; SEND_RATE
  3700                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3701                              <1> ; ON ENTRY:	DI = DRIVE #
  3702                              <1> ; ON EXIT:	NONE
  3703                              <1> ; REGISTERS ALTERED: DX
  3704                              <1> ;-------------------------------------------------------------------------------
  3705                              <1> SEND_RATE:
  3706                              <1> 	;PUSH	AX			; SAVE REG.
  3707                              <1> 	; 24/12/2021
  3708 00001EB9 50                  <1> 	push	eax
  3709 00001EBA 8025[146C0000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3710 00001EC1 8A87[196C0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3711 00001EC7 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3712 00001EC9 0805[146C0000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3713 00001ECF C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3714 00001ED2 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3715 00001ED6 EE                  <1> 	OUT	DX,AL
  3716                              <1> 	;POP	AX			; RESTORE REG.
  3717                              <1> 	; 24/12/2021
  3718 00001ED7 58                  <1> 	pop	eax
  3719 00001ED8 C3                  <1> 	RETn
  3720                              <1> 
  3721                              <1> ;-------------------------------------------------------------------------------
  3722                              <1> ; CHK_LASTRATE
  3723                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3724                              <1> ; ON ENTRY:
  3725                              <1> ;	DI = DRIVE #
  3726                              <1> ; ON EXIT:
  3727                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3728                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3729                              <1> ; REGISTERS ALTERED: DX
  3730                              <1> ;-------------------------------------------------------------------------------
  3731                              <1> CHK_LASTRATE:
  3732                              <1> 	;PUSH	AX			; SAVE REG.
  3733                              <1> 	; 24/12/2021
  3734 00001ED9 50                  <1> 	push	eax
  3735 00001EDA 2225[146C0000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3736 00001EE0 8A87[196C0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3737 00001EE6 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3738 00001EEA 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3739                              <1> 					; ZF = 1 RATE IS THE SAME
  3740                              <1> 	;POP	AX			; RESTORE REG.
  3741                              <1> 	; 24/12/2021
  3742 00001EEC 58                  <1> 	pop	eax
  3743 00001EED C3                  <1> 	RETn
  3744                              <1> 
  3745                              <1> ;-------------------------------------------------------------------------------
  3746                              <1> ; DMA_SETUP
  3747                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3748                              <1> ;
  3749                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3750                              <1> ;
  3751                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3752                              <1> ;-------------------------------------------------------------------------------
  3753                              <1> 
  3754                              <1> ; SI = Head #, # of Sectors or DASD Type
  3755                              <1> 
  3756                              <1> ; 22/08/2015
  3757                              <1> ; 08/02/2015 - Protected Mode Modification
  3758                              <1> ; 06/02/2015 - 07/02/2015
  3759                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3760                              <1> ; (DMA Addres = Physical Address)
  3761                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3762                              <1> ;
  3763                              <1> ; 04/02/2016 (clc)
  3764                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3765                              <1> ; 16/12/2014 (IODELAY)
  3766                              <1> 
  3767                              <1> DMA_SETUP:
  3768                              <1> 
  3769                              <1> ;; 20/02/2015
  3770 00001EEE 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3771 00001EF1 F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3772 00001EF7 7569                <1> 	jnz	short dma_bnd_err_stc
  3773                              <1> 	;
  3774                              <1> 	;push	ax			; DMA command
  3775                              <1> 	; 24/12/2021
  3776 00001EF9 50                  <1> 	push	eax
  3777 00001EFA 52                  <1> 	push	edx			; *
  3778 00001EFB B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3779 00001EFD E840030000          <1> 	call	GET_PARM		; 
  3780 00001F02 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3781                              <1> 	;mov	ax, si			; Sector count
  3782                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3783                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3784                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3785                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3786                              <1> 	; 24/12/2021
  3787 00001F04 89F2                <1> 	mov	edx, esi
  3788 00001F06 29C0                <1> 	sub	eax, eax
  3789 00001F08 88D4                <1> 	mov	ah, dl
  3790 00001F0A D1E8                <1> 	shr	eax, 1
  3791 00001F0C D3E0                <1> 	shl	eax, cl
  3792                              <1> 	;
  3793 00001F0E 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3794 00001F10 6689C1              <1> 	mov	cx, ax
  3795 00001F13 5A                  <1> 	pop	edx			; *
  3796                              <1> 	;pop	ax
  3797                              <1> 	; 24/12/2021
  3798 00001F14 58                  <1> 	pop	eax
  3799 00001F15 3C42                <1> 	cmp	al, 42h
  3800 00001F17 7507                <1>         jne     short NOT_VERF
  3801 00001F19 BA0000FF00          <1> 	mov	edx, 0FF0000h
  3802 00001F1E EB08                <1> 	jmp	short J33
  3803                              <1> NOT_VERF:
  3804 00001F20 6601CA              <1> 	add	dx, cx			; check for overflow
  3805 00001F23 723E                <1> 	jc	short dma_bnd_err
  3806                              <1> 	;
  3807 00001F25 6629CA              <1> 	sub	dx, cx			; Restore start address
  3808                              <1> J33:
  3809 00001F28 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3810 00001F29 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3811                              <1> 	IODELAY				; WAIT FOR I/O
  2153 00001F2B EB00                <2>  jmp short $+2
  2154 00001F2D EB00                <2>  jmp short $+2
  3812 00001F2F E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3813 00001F31 89D0                <1> 	mov	eax,edx			; Buffer address
  3814 00001F33 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3815                              <1> 	IODELAY				; WAIT FOR I/O
  2153 00001F35 EB00                <2>  jmp short $+2
  2154 00001F37 EB00                <2>  jmp short $+2
  3816 00001F39 88E0                <1> 	MOV	AL,AH
  3817 00001F3B E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3818 00001F3D C1E810              <1> 	shr	eax,16
  3819                              <1> 	IODELAY				; I/O WAIT STATE
  2153 00001F40 EB00                <2>  jmp short $+2
  2154 00001F42 EB00                <2>  jmp short $+2
  3820 00001F44 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3821                              <1> 	IODELAY
  2153 00001F46 EB00                <2>  jmp short $+2
  2154 00001F48 EB00                <2>  jmp short $+2
  3822 00001F4A 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3823 00001F4D E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3824                              <1> 	IODELAY				; WAIT FOR I/O
  2153 00001F4F EB00                <2>  jmp short $+2
  2154 00001F51 EB00                <2>  jmp short $+2
  3825 00001F53 88E0                <1> 	MOV	AL,AH
  3826 00001F55 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3827                              <1> 	IODELAY
  2153 00001F57 EB00                <2>  jmp short $+2
  2154 00001F59 EB00                <2>  jmp short $+2
  3828 00001F5B FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3829 00001F5C B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3830 00001F5E E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3831                              <1> 
  3832 00001F60 F8                  <1> 	clc	; 04/02/2016
  3833 00001F61 C3                  <1> 	retn
  3834                              <1> 
  3835                              <1> dma_bnd_err_stc:
  3836 00001F62 F9                  <1> 	stc
  3837                              <1> dma_bnd_err:
  3838 00001F63 C605[0C6C0000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3839 00001F6A C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3840                              <1> 
  3841                              <1> ;; 16/12/2014
  3842                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3843                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3844                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3845                              <1> ;;	IODELAY
  3846                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3847                              <1> ;;	;SIODELAY
  3848                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3849                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3850                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3851                              <1> ;;      ;JMP	SHORT J33
  3852                              <1> ;;;NOT_VERF:	
  3853                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3854                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3855                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3856                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3857                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3858                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3859                              <1> ;;	;JNC	short J33
  3860                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3861                              <1> ;;;J33:
  3862                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3863                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3864                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3865                              <1> ;;	IODELAY
  3866                              <1> ;;	MOV	AL,AH
  3867                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3868                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3869                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3870                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3871                              <1> ;;	IODELAY
  3872                              <1> ;;	;AND	AL,00001111B
  3873                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3874                              <1> ;;	;SIODELAY
  3875                              <1> ;;
  3876                              <1> ;;;----- DETERMINE COUNT
  3877                              <1> ;;	sub	eax, eax ; 08/02/2015
  3878                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3879                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3880                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3881                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3882                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3883                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3884                              <1> ;;	CALL	GET_PARM		; "
  3885                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3886                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3887                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3888                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3889                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3890                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3891                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3892                              <1> ;;	IODELAY
  3893                              <1> ;;	MOV	AL, AH
  3894                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3895                              <1> ;;	;IODELAY
  3896                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3897                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3898                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3899                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3900                              <1> ;;	add	ecx, eax ; 08/02/2015
  3901                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3902                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3903                              <1> ;;	SIODELAY
  3904                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3905                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3906                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3907                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3908                              <1> ;;	jz	short NO_BAD
  3909                              <1> ;;dma_bnd_err:
  3910                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3911                              <1> ;;NO_BAD:
  3912                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3913                              <1> 
  3914                              <1> ;-------------------------------------------------------------------------------
  3915                              <1> ; FMTDMA_SET
  3916                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3917                              <1> ;
  3918                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3919                              <1> ;
  3920                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3921                              <1> ;-------------------------------------------------------------------------------
  3922                              <1> 
  3923                              <1> 	; 24/12/2021
  3924                              <1> FMTDMA_SET:
  3925                              <1> ;; 20/02/2015 modification	
  3926 00001F6B 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3927 00001F6E F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3928 00001F74 75EC                <1> 	jnz	short dma_bnd_err_stc
  3929                              <1> 	;
  3930                              <1> 	;push	dx			; *
  3931                              <1> 	; 24/12/2021
  3932 00001F76 52                  <1> 	push	edx
  3933 00001F77 B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3934 00001F79 E8C4020000          <1> 	call	GET_PARM		; "
  3935                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3936                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3937                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3938                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3939                              <1> 	;mov	cx, ax
  3940                              <1> 	; 24/12/2021
  3941 00001F7E 29C9                <1> 	sub	ecx, ecx
  3942 00001F80 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3943 00001F82 D1E1                <1> 	shl	ecx, 1
  3944 00001F84 D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3945 00001F86 6649                <1> 	dec	cx
  3946                              <1> 	;pop	dx			; *
  3947                              <1> 	; 24/12/2021
  3948 00001F88 5A                  <1> 	pop	edx
  3949 00001F89 6601CA              <1> 	add	dx, cx			; check for overflow
  3950 00001F8C 72D5                <1> 	jc	short dma_bnd_err
  3951                              <1> 	;
  3952 00001F8E 6629CA              <1> 	sub	dx, cx			; Restore start address
  3953                              <1> 	;
  3954 00001F91 B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3955 00001F93 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3956 00001F94 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3957                              <1> 	IODELAY				; WAIT FOR I/O
  2153 00001F96 EB00                <2>  jmp short $+2
  2154 00001F98 EB00                <2>  jmp short $+2
  3958 00001F9A E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3959 00001F9C 89D0                <1> 	mov	eax,edx			; Buffer address
  3960 00001F9E E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3961                              <1> 	IODELAY				; WAIT FOR I/O
  2153 00001FA0 EB00                <2>  jmp short $+2
  2154 00001FA2 EB00                <2>  jmp short $+2
  3962 00001FA4 88E0                <1> 	MOV	AL,AH
  3963 00001FA6 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3964 00001FA8 C1E810              <1> 	shr	eax,16
  3965                              <1> 	IODELAY				; I/O WAIT STATE
  2153 00001FAB EB00                <2>  jmp short $+2
  2154 00001FAD EB00                <2>  jmp short $+2
  3966 00001FAF E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3967                              <1> 	IODELAY
  2153 00001FB1 EB00                <2>  jmp short $+2
  2154 00001FB3 EB00                <2>  jmp short $+2
  3968 00001FB5 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3969 00001FB8 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3970                              <1> 	IODELAY				; WAIT FOR I/O
  2153 00001FBA EB00                <2>  jmp short $+2
  2154 00001FBC EB00                <2>  jmp short $+2
  3971 00001FBE 88E0                <1> 	MOV	AL,AH
  3972 00001FC0 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3973                              <1> 	IODELAY
  2153 00001FC2 EB00                <2>  jmp short $+2
  2154 00001FC4 EB00                <2>  jmp short $+2
  3974 00001FC6 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3975 00001FC7 B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3976 00001FC9 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3977 00001FCB C3                  <1> 	retn
  3978                              <1> 
  3979                              <1> ;; 08/02/2015 - Protected Mode Modification
  3980                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3981                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3982                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3983                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3984                              <1> ;;	IODELAY
  3985                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3986                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3987                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3988                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3989                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3990                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3991                              <1> ;;	;JNC	short J33A
  3992                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3993                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3994                              <1> ;;;J33A:
  3995                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3996                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3997                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3998                              <1> ;;	IODELAY
  3999                              <1> ;;	MOV	AL,AH
  4000                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  4001                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  4002                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  4003                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  4004                              <1> ;;	IODELAY
  4005                              <1> ;;	;AND	AL,00001111B
  4006                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  4007                              <1> ;;
  4008                              <1> ;;;----- DETERMINE COUNT
  4009                              <1> ;;	sub	eax, eax ; 08/02/2015
  4010                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  4011                              <1> ;;	CALL	GET_PARM		; "
  4012                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  4013                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  4014                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  4015                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  4016                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  4017                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  4018                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4019                              <1> ;;	IODELAY
  4020                              <1> ;;	MOV	AL, AH
  4021                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  4022                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  4023                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  4024                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  4025                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  4026                              <1> ;;	add	ecx, eax ; 08/02/2015
  4027                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  4028                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4029                              <1> ;;	SIODELAY
  4030                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  4031                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  4032                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  4033                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  4034                              <1> ;;	jz	short FMTDMA_OK
  4035                              <1> ;;	stc	; 20/02/2015
  4036                              <1> ;;fmtdma_bnd_err:
  4037                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  4038                              <1> ;;FMTDMA_OK:
  4039                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  4040                              <1> 
  4041                              <1> ;-------------------------------------------------------------------------------
  4042                              <1> ; NEC_INIT	
  4043                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  4044                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  4045                              <1> ;
  4046                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  4047                              <1> ;
  4048                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4049                              <1> ;-------------------------------------------------------------------------------
  4050                              <1> NEC_INIT:
  4051                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  4052                              <1> 	; 24/12/2021
  4053 00001FCC 50                  <1> 	push	eax
  4054 00001FCD E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  4055                              <1> 
  4056                              <1> ;-----	DO THE SEEK OPERATION
  4057                              <1> 
  4058 00001FD2 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  4059 00001FD5 E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  4060                              <1> 	;POP	AX			; RECOVER COMMAND
  4061                              <1> 	; 24/12/2021
  4062 00001FDA 58                  <1> 	pop	eax
  4063 00001FDB 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  4064 00001FDD BB[FB1F0000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  4065 00001FE2 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  4066                              <1> 
  4067                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  4068                              <1> 
  4069 00001FE3 E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  4070 00001FE8 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  4071 00001FEB 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  4072 00001FED C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  4073 00001FF0 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  4074 00001FF3 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  4075 00001FF5 E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  4076 00001FFA 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  4077                              <1> ER_1:
  4078 00001FFB C3                  <1> 	RETn
  4079                              <1> 
  4080                              <1> ;-------------------------------------------------------------------------------
  4081                              <1> ; RWV_COM
  4082                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  4083                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  4084                              <1> ;
  4085                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  4086                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4087                              <1> ;-------------------------------------------------------------------------------
  4088                              <1> RWV_COM:
  4089 00001FFC B8[47200000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  4090 00002001 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  4091 00002002 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  4092 00002005 E83E030000          <1> 	CALL	NEC_OUTPUT
  4093 0000200A 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  4094 0000200D E836030000          <1> 	CALL	NEC_OUTPUT
  4095 00002012 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  4096 00002015 E82E030000          <1> 	CALL	NEC_OUTPUT
  4097 0000201A B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  4098 0000201C E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4099 00002021 E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4100 00002026 B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  4101 00002028 E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4102 0000202D E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4103 00002032 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  4104                              <1> _R15:
  4105 00002035 E80E030000          <1> 	CALL	NEC_OUTPUT
  4106 0000203A B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  4107 0000203C E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  4108 00002041 E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4109 00002046 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4110                              <1> ER_2:
  4111 00002047 C3                  <1> 	RETn
  4112                              <1> 
  4113                              <1> ;-------------------------------------------------------------------------------
  4114                              <1> ; NEC_TERM
  4115                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4116                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4117                              <1> ;
  4118                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4119                              <1> ;-------------------------------------------------------------------------------
  4120                              <1> NEC_TERM:
  4121                              <1> 
  4122                              <1> ;-----	LET THE OPERATION HAPPEN
  4123                              <1> 
  4124 00002048 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4125 00002049 E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4126 0000204E 9C                  <1> 	PUSHFd	; 24/12/2021
  4127 0000204F E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4128 00002054 724B                <1> 	JC	short SET_END_POP
  4129 00002056 9D                  <1> 	POPFd	; 24/12/2021
  4130 00002057 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4131                              <1> 
  4132                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4133                              <1> 
  4134 00002059 FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4135 0000205A BE[0D6C0000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4136 0000205F AC                  <1> 	lodsb				; GET ST0
  4137 00002060 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4138 00002062 7433                <1> 	JZ	short SET_END
  4139 00002064 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4140 00002066 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4141                              <1> 
  4142                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4143                              <1> 
  4144 00002068 AC                  <1> 	lodsb				; GET ST1
  4145 00002069 D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4146 0000206B B404                <1> 	MOV	AH,RECORD_NOT_FND
  4147 0000206D 7222                <1> 	JC	short J19
  4148 0000206F C0E002              <1> 	SAL	AL,2
  4149 00002072 B410                <1> 	MOV	AH,BAD_CRC
  4150 00002074 721B                <1> 	JC	short J19
  4151 00002076 D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4152 00002078 B408                <1> 	MOV	AH,BAD_DMA
  4153 0000207A 7215                <1> 	JC	short J19
  4154 0000207C C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4155 0000207F B404                <1> 	MOV	AH,RECORD_NOT_FND
  4156 00002081 720E                <1> 	JC	short J19
  4157 00002083 D0E0                <1> 	SAL	AL,1
  4158 00002085 B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4159 00002087 7208                <1> 	JC	short J19
  4160 00002089 D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4161 0000208B B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4162 0000208D 7202                <1> 	JC	short J19
  4163                              <1> 
  4164                              <1> ;----- 	NEC MUST HAVE FAILED
  4165                              <1> J18:
  4166 0000208F B420                <1> 	MOV	AH,BAD_NEC
  4167                              <1> J19:
  4168 00002091 0825[0C6C0000]      <1> 	OR	[DSKETTE_STATUS],AH
  4169                              <1> SET_END:
  4170 00002097 803D[0C6C0000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4171 0000209E F5                  <1> 	CMC
  4172 0000209F 5E                  <1> 	POP	eSI
  4173 000020A0 C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4174                              <1> 
  4175                              <1> SET_END_POP:
  4176 000020A1 9D                  <1> 	POPFd	; 24/12/2021
  4177 000020A2 EBF3                <1> 	JMP	SHORT SET_END
  4178                              <1> 
  4179                              <1> ;-------------------------------------------------------------------------------
  4180                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4181                              <1> ;-------------------------------------------------------------------------------
  4182                              <1> DSTATE:
  4183 000020A4 803D[0C6C0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4184 000020AB 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4185 000020AD 808F[196C0000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4186 000020B4 F687[196C0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4187 000020BB 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4188 000020BD 8A87[196C0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4189 000020C3 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4190 000020C5 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4191 000020C7 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4192                              <1> 
  4193                              <1> ;----- 	CHECK IF IT IS 1.44M
  4194                              <1> 
  4195 000020C9 E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4196                              <1> 	;;20/02/2015
  4197                              <1> 	;;JC	short M_12		; CMOS BAD
  4198 000020CE 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4199 000020D0 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4200 000020D2 7410                <1> 	JE	short M_12		; YES
  4201                              <1> M_720:
  4202 000020D4 80A7[196C0000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4203 000020DB 808F[196C0000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4204 000020E2 EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4205                              <1> M_12:	
  4206 000020E4 808F[196C0000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4207                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4208                              <1> SETBAC:
  4209 000020EB C3                  <1> 	RETn
  4210                              <1> 
  4211                              <1> ;-------------------------------------------------------------------------------
  4212                              <1> ; RETRY	
  4213                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4214                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4215                              <1> ;
  4216                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4217                              <1> ;-------------------------------------------------------------------------------
  4218                              <1> RETRY:
  4219 000020EC 803D[0C6C0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4220 000020F3 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4221 000020F5 803D[0C6C0000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4222 000020FC 743C                <1> 	JZ	short NO_RETRY
  4223 000020FE 8AA7[196C0000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4224 00002104 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4225 00002107 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4226 00002109 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4227 0000210C 8A2D[146C0000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4228 00002112 C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4229 00002115 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4230 00002118 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4231 0000211A 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4232                              <1> 
  4233                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4234                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4235                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4236                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4237                              <1> 
  4238 0000211C 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4239 0000211F D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4240 00002121 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4241 00002124 80A7[196C0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4242                              <1> 					; RATE, DBL STEP OFF
  4243 0000212B 08A7[196C0000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4244 00002131 C605[0C6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4245 00002138 F9                  <1> 	STC				; SET CARRY FOR RETRY
  4246 00002139 C3                  <1> 	RETn				; RETRY RETURN
  4247                              <1> 
  4248                              <1> NO_RETRY:
  4249 0000213A F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4250 0000213B C3                  <1> 	RETn				; NO RETRY RETURN
  4251                              <1> 
  4252                              <1> ;-------------------------------------------------------------------------------
  4253                              <1> ; NUM_TRANS
  4254                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4255                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4256                              <1> ;
  4257                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4258                              <1> ;		SI-HI  = HEAD
  4259                              <1> ;		[BP]   = START SECTOR
  4260                              <1> ;
  4261                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4262                              <1> ;-------------------------------------------------------------------------------
  4263                              <1> NUM_TRANS:
  4264 0000213C 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4265 0000213E 803D[0C6C0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4266                              <1> 	; 24/12/2021
  4267 00002145 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4268 00002147 B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4269 00002149 E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4270 0000214E 8A1D[126C0000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4271 00002154 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4272 00002157 3A2D[116C0000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4273 0000215D 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4274 0000215F 8A2D[106C0000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4275 00002165 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4276 00002168 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4277 0000216A 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4278                              <1> DIF_HD:
  4279 0000216C 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4280                              <1> SAME_TRK:
  4281 0000216E 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4282 00002171 88D8                <1> 	MOV	AL,BL			; TO AL
  4283                              <1> NT_OUT:
  4284 00002173 C3                  <1> 	RETn
  4285                              <1> 
  4286                              <1> ;-------------------------------------------------------------------------------
  4287                              <1> ; SETUP_END
  4288                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4289                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4290                              <1> ;
  4291                              <1> ; ON EXIT:
  4292                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4293                              <1> ;-------------------------------------------------------------------------------
  4294                              <1> SETUP_END:
  4295 00002174 B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4296                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4297 00002176 50                  <1> 	push	eax ; 24/12/2021
  4298 00002177 E8C6000000          <1> 	CALL	GET_PARM
  4299 0000217C 8825[0B6C0000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4300                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4301 00002182 58                  <1> 	pop	eax ; 24/12/2021
  4302 00002183 8A25[0C6C0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4303 00002189 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4304 0000218B 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4305 0000218D 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4306                              <1> NUN_ERR: 
  4307 0000218F 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4308 00002192 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4309 00002193 C3                  <1> 	RETn
  4310                              <1> 
  4311                              <1> ;-------------------------------------------------------------------------------
  4312                              <1> ; SETUP_DBL
  4313                              <1> ;	CHECK DOUBLE STEP.
  4314                              <1> ;
  4315                              <1> ; ON ENTRY :	DI = DRIVE
  4316                              <1> ;
  4317                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4318                              <1> ;-------------------------------------------------------------------------------
  4319                              <1> SETUP_DBL:
  4320 00002194 8AA7[196C0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4321 0000219A F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4322 0000219D 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4323                              <1> 
  4324                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4325                              <1> 
  4326 0000219F C605[096C0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4327 000021A6 E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4328 000021AB B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4329 000021AD E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4330 000021B2 E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4331 000021B7 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4332                              <1> 
  4333                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4334                              <1> 
  4335 000021B9 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4336 000021BD F687[196C0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4337 000021C4 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4338 000021C6 B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4339                              <1> 
  4340                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4341                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4342                              <1> ;	THEN SET DOUBLE STEP ON.
  4343                              <1> 
  4344                              <1> CNT_OK:
  4345 000021C8 C605[0B6C0000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4346                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4347                              <1> 	; 24/12/2021
  4348 000021CF 51                  <1> 	push	ecx
  4349 000021D0 C605[0C6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4350 000021D7 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4351 000021DA D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4352 000021DC C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4353                              <1> 	;PUSH	AX			; SAVE HEAD
  4354                              <1> 	; 24/12/2021
  4355 000021DF 50                  <1> 	push	eax
  4356 000021E0 E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4357                              <1> 	;POP	AX			; RESTORE HEAD
  4358                              <1> 	; 24/12/2021
  4359 000021E5 58                  <1> 	pop	eax
  4360 000021E6 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4361 000021E9 E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4362 000021EE 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4363 000021EF 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4364 000021F4 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4365                              <1> 	;POP	CX			; RESTORE COUNT
  4366                              <1> 	; 24/12/2021
  4367 000021F5 59                  <1> 	pop	ecx
  4368 000021F6 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4369 000021F8 FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4370 000021FA 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4371 000021FC 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4372                              <1> 
  4373                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4374                              <1> 
  4375                              <1> SD_ERR:	
  4376 000021FE F9                  <1> 	STC				; SET CARRY FOR ERROR
  4377 000021FF C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4378                              <1> 
  4379                              <1> DO_CHK:
  4380 00002200 8A0D[106C0000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4381 00002206 888F[1D6C0000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4382 0000220C D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4383 0000220E 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4384 00002210 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4385 00002212 808F[196C0000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4386                              <1> NO_DBL:
  4387 00002219 F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4388 0000221A C3                  <1> 	RETn
  4389                              <1> 
  4390                              <1> ;-------------------------------------------------------------------------------
  4391                              <1> ; READ_ID
  4392                              <1> ;	READ ID FUNCTION.
  4393                              <1> ;
  4394                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4395                              <1> ;
  4396                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4397                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4398                              <1> ;-------------------------------------------------------------------------------
  4399                              <1> READ_ID:
  4400 0000221B B8[38220000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4401 00002220 50                  <1> 	PUSH	eAX
  4402 00002221 B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4403 00002223 E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4404 00002228 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4405 0000222B 88C4                <1> 	MOV	AH,AL
  4406 0000222D E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4407 00002232 E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4408 00002237 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4409                              <1> ER_3:
  4410 00002238 C3                  <1> 	RETn
  4411                              <1> 
  4412                              <1> ;-------------------------------------------------------------------------------
  4413                              <1> ; CMOS_TYPE
  4414                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4415                              <1> ;
  4416                              <1> ; ON ENTRY:	DI = DRIVE #
  4417                              <1> ;
  4418                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4419                              <1> ;-------------------------------------------------------------------------------
  4420                              <1> 
  4421                              <1> CMOS_TYPE: ; 11/12/2014
  4422 00002239 8A87[7E660000]      <1> 	mov	al, [eDI+fd0_type]
  4423 0000223F 20C0                <1> 	and 	al, al ; 18/12/2014
  4424 00002241 C3                  <1> 	retn
  4425                              <1> 
  4426                              <1> ;CMOS_TYPE:
  4427                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4428                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4429                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4430                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4431                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4432                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4433                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4434                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4435                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4436                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4437                              <1> ;TB:
  4438                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4439                              <1> ;BAD_CM:
  4440                              <1> ;	RETn				; CY, STATUS OF READ
  4441                              <1> 
  4442                              <1> ;-------------------------------------------------------------------------------
  4443                              <1> ; GET_PARM
  4444                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4445                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4446                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4447                              <1> ;	THE PARAMETER IN DL.
  4448                              <1> ;
  4449                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4450                              <1> ;
  4451                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4452                              <1> ;		AL,DH DESTROYED
  4453                              <1> ;-------------------------------------------------------------------------------
  4454                              <1> GET_PARM:
  4455                              <1> 	;PUSH	DS
  4456 00002242 56                  <1> 	PUSH	eSI
  4457                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4458                              <1>     	;MOV	DS,AX
  4459                              <1> 	;;mov	ax, cs
  4460                              <1> 	;;mov	ds, ax
  4461                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4462 00002243 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4463                              <1> 	;SUB	BH,BH			; BX = INDEX
  4464 00002245 81E3FF000000        <1> 	and	ebx, 0FFh
  4465                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4466                              <1> 	;
  4467                              <1> 	; 17/12/2014
  4468 0000224B 66A1[71660000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4469 00002251 38E0                <1> 	cmp	al, ah
  4470 00002253 7425                <1> 	je	short gpndc
  4471 00002255 A2[72660000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4472 0000225A 53                  <1> 	push	ebx ; 08/02/2015
  4473 0000225B 88C3                <1> 	mov	bl, al 
  4474                              <1> 	; 11/12/2014
  4475 0000225D 8A83[7E660000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4476                              <1> 	; 18/12/2014
  4477 00002263 20C0                <1> 	and	al, al
  4478 00002265 7507                <1> 	jnz	short gpdtc
  4479 00002267 BB[5B660000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4480 0000226C EB05                <1>         jmp     short gpdpu
  4481                              <1> gpdtc:	
  4482 0000226E E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4483                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4484                              <1> gpdpu:
  4485 00002273 891D[F8650000]      <1> 	mov	[DISK_POINTER], ebx
  4486 00002279 5B                  <1> 	pop	ebx
  4487                              <1> gpndc:
  4488 0000227A 8B35[F8650000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4489 00002280 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4490 00002283 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4491 00002285 5E                  <1> 	POP	eSI
  4492                              <1> 	;POP	DS
  4493 00002286 C3                  <1> 	RETn
  4494                              <1> 
  4495                              <1> ;-------------------------------------------------------------------------------
  4496                              <1> ; MOTOR_ON
  4497                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4498                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4499                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4500                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4501                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4502                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4503                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4504                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4505                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4506                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4507                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4508                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4509                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4510                              <1> ;
  4511                              <1> ; ON ENTRY:	DI = DRIVE #
  4512                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4513                              <1> ;-------------------------------------------------------------------------------
  4514                              <1> MOTOR_ON:
  4515 00002287 53                  <1> 	PUSH	eBX			; SAVE REG.
  4516 00002288 E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4517 0000228D 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4518 0000228F E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4519 00002294 E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4520                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4521                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4522                              <1> M_WAIT:
  4523 00002299 B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4524 0000229B E8A2FFFFFF          <1> 	CALL	GET_PARM
  4525                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4526                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4527                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4528 000022A0 80FC08              <1> 	cmp	ah, 8
  4529                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4530 000022A3 7702                <1> 	ja	short J13
  4531                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4532 000022A5 B408                <1> 	mov	ah, 8
  4533                              <1> 
  4534                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4535                              <1> GP2:	
  4536                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4537                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4538 000022A7 B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4539 000022AC E80BF2FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4540                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4541 000022B1 FECC                <1> 	dec	ah
  4542 000022B3 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4543                              <1> MOT_IS_ON:
  4544 000022B5 5B                  <1> 	POP	eBX			; RESTORE REG.
  4545 000022B6 C3                  <1> 	RETn
  4546                              <1> 
  4547                              <1> ;-------------------------------------------------------------------------------
  4548                              <1> ; TURN_ON
  4549                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4550                              <1> ;
  4551                              <1> ; ON ENTRY:	DI = DRIVE #
  4552                              <1> ;
  4553                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4554                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4555                              <1> ;		AX,BX,CX,DX DESTROYED
  4556                              <1> ;-------------------------------------------------------------------------------
  4557                              <1> TURN_ON:
  4558 000022B7 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4559 000022B9 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4560 000022BB C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4561 000022BE FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4562 000022BF C605[0B6C0000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4563 000022C6 A0[0A6C0000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4564 000022CB 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4565 000022CD B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4566 000022CF D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4567                              <1> 
  4568                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4569                              <1> ;  BL = DRIVE SELECT DESIRED
  4570                              <1> ;  AH = MOTOR ON MASK DESIRED
  4571                              <1> 
  4572 000022D1 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4573 000022D3 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4574 000022D5 8425[0A6C0000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4575 000022DB 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4576                              <1> 
  4577                              <1> TURN_IT_ON:
  4578 000022DD 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4579 000022DF 8A3D[0A6C0000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4580 000022E5 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4581 000022E8 8025[0A6C0000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4582 000022EF 0825[0A6C0000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4583 000022F5 A0[0A6C0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4584 000022FA 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4585 000022FC 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4586 000022FF FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4587 00002300 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4588 00002302 C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4589 00002305 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4590 00002307 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4591 0000230B EE                  <1> 	OUT	DX,AL
  4592 0000230C 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4593                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4594 0000230E 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4595 00002310 F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4596 00002311 C3                  <1> 	RETn
  4597                              <1> 
  4598                              <1> NO_MOT_WAIT:
  4599 00002312 FB                  <1> 	sti
  4600                              <1> no_mot_w1: ; 27/02/2015
  4601 00002313 F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4602                              <1> 	;STI				; INTERRUPTS BACK ON
  4603 00002314 C3                  <1> 	RETn
  4604                              <1> 
  4605                              <1> ;-------------------------------------------------------------------------------
  4606                              <1> ; HD_WAIT
  4607                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4608                              <1> ;
  4609                              <1> ; ON ENTRY:	DI = DRIVE #
  4610                              <1> ;
  4611                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4612                              <1> ;-------------------------------------------------------------------------------
  4613                              <1> HD_WAIT:
  4614 00002315 B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4615 00002317 E826FFFFFF          <1> 	CALL	GET_PARM
  4616 0000231C 08E4                <1> 	or	ah, ah	; 17/12/2014
  4617 0000231E 7519                <1> 	jnz	short DO_WAT
  4618 00002320 F605[0A6C0000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4619                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4620                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4621                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4622 00002327 741E                <1> 	jz	short HW_DONE
  4623 00002329 B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4624 0000232B 8A87[196C0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4625 00002331 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4626 00002333 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4627 00002335 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4628                              <1> ;GP3:
  4629 00002337 B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4630                              <1> ;	JMP	SHORT DO_WAT
  4631                              <1> 
  4632                              <1> ;ISNT_WRITE:
  4633                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4634                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4635                              <1> 
  4636                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4637                              <1> DO_WAT:
  4638                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4639                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4640                              <1> J29:					; 	1 MILLISECOND LOOP
  4641                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4642 00002339 B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4643 0000233E E879F1FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4644                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4645 00002343 FECC                <1> 	dec	ah
  4646 00002345 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4647                              <1> HW_DONE:
  4648 00002347 C3                  <1> 	RETn
  4649                              <1> 
  4650                              <1> ;-------------------------------------------------------------------------------
  4651                              <1> ; NEC_OUTPUT
  4652                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4653                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4654                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4655                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4656                              <1> ; 
  4657                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4658                              <1> ;
  4659                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4660                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4661                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4662                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4663                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4664                              <1> ;		AX,CX,DX DESTROYED
  4665                              <1> ;-------------------------------------------------------------------------------
  4666                              <1> 
  4667                              <1> ; 09/12/2014 [Erdogan Tan] 
  4668                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4669                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4670                              <1> ;	This read only register facilitates the transfer of data between
  4671                              <1> ;	the system microprocessor and the controller.
  4672                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4673                              <1> ;	  with the system micrprocessor.
  4674                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4675                              <1> ;	  the transfer is to the controller.
  4676                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4677                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4678                              <1> ; Bit 3 - Reserved.
  4679                              <1> ; Bit 2 - Reserved.
  4680                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4681                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4682                              <1> 
  4683                              <1> ; Data Register (3F5h)
  4684                              <1> ; This read/write register passes data, commands and parameters, and provides
  4685                              <1> ; diskette status information.
  4686                              <1>   		
  4687                              <1> NEC_OUTPUT:
  4688                              <1> 	;PUSH	BX			; SAVE REG.
  4689 00002348 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4690                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4691                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4692                              <1> 	; 16/12/2014
  4693                              <1> 	; waiting for (max.) 0.5 seconds
  4694                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4695                              <1> 	;
  4696                              <1> 	; 17/12/2014
  4697                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4698                              <1> 	;
  4699                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4700                              <1> 	;		go on.
  4701                              <1> 	;INPUT:
  4702                              <1> 	;	AH=Mask for isolation bits.
  4703                              <1> 	;	AL=pattern to look for.
  4704                              <1> 	;	DX=Port to test for
  4705                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4706                              <1> 	;	     (normally 30 microseconds per period.)
  4707                              <1> 	;
  4708                              <1> 	;WFP_SHORT:  
  4709                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4710                              <1> 	;
  4711                              <1> 
  4712                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4713                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4714 0000234C B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4715                              <1> ;
  4716                              <1> ;WFPS_OUTER_LP:
  4717                              <1> ;	;
  4718                              <1> ;WFPS_CHECK_PORT:
  4719                              <1> J23:
  4720 00002351 EC                  <1> 	IN	AL,DX			; GET STATUS
  4721 00002352 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4722 00002354 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4723 00002356 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4724                              <1> WFPS_HI:
  4725 00002358 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4726 0000235A A810                <1> 	TEST	AL,010H			; transition on memory
  4727 0000235C 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4728                              <1> WFPS_LO:
  4729 0000235E E461                <1> 	IN	AL, PORT_B		; SYS1
  4730 00002360 A810                <1> 	TEST	AL,010H
  4731 00002362 74FA                <1> 	JZ	SHORT WFPS_LO
  4732                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4733 00002364 E2EB                <1> 	loop	J23	; 27/02/2015
  4734                              <1> ;	;
  4735                              <1> ;	dec	bl
  4736                              <1> ;	jnz	short WFPS_OUTER_LP
  4737                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4738                              <1> ;J23:
  4739                              <1> ;	IN	AL,DX			; GET STATUS
  4740                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4741                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4742                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4743                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4744                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4745                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4746                              <1>    
  4747                              <1> 	;;27/02/2015
  4748                              <1> 	;16/12/2014
  4749                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4750                              <1> 	;;jb	short J23
  4751                              <1> 
  4752                              <1> ;WFPS_TIMEOUT:
  4753                              <1> 
  4754                              <1> ;-----	FALL THRU TO ERROR RETURN
  4755                              <1> 
  4756 00002366 800D[0C6C0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4757                              <1> 	;POP	BX			; RESTORE REG.
  4758 0000236D 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4759 0000236E F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4760 0000236F C3                  <1> 	RETn
  4761                              <1> 
  4762                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4763                              <1> 
  4764                              <1> J27:	
  4765 00002370 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4766 00002372 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4767 00002374 EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4768                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4769                              <1> 	; 27/02/2015
  4770 00002375 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE FLAGS
  4771                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4772 00002376 29C9                <1> 	sub	ecx, ecx
  4773 00002378 B103                <1> 	mov	cl, 3 ; 24/12/2021
  4774 0000237A E83DF1FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4775 0000237F 9D                  <1> 	POPFd	; 24/12/2021			; RESTORE FLAGS FOR EXIT
  4776                              <1> 	;POP	BX			; RESTORE REG
  4777 00002380 C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4778                              <1> 
  4779                              <1> ;-------------------------------------------------------------------------------
  4780                              <1> ; SEEK
  4781                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4782                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4783                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4784                              <1> ;
  4785                              <1> ; ON ENTRY:	DI = DRIVE #
  4786                              <1> ;		CH = TRACK #
  4787                              <1> ;
  4788                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4789                              <1> ;		AX,BX,CX DX DESTROYED
  4790                              <1> ;-------------------------------------------------------------------------------
  4791                              <1> SEEK:
  4792 00002381 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4793 00002383 B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4794 00002385 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4795 00002387 D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4796 00002389 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4797 0000238B 8405[096C0000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4798 00002391 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4799                              <1> 
  4800 00002393 0805[096C0000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4801 00002399 E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4802 0000239E 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4803                              <1> 
  4804                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4805                              <1> 
  4806 000023A0 C605[0C6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4807 000023A7 E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4808 000023AC 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4809                              <1> 
  4810                              <1> AFT_RECAL:
  4811 000023AE C687[1D6C0000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4812 000023B5 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4813 000023B7 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4814                              <1> 
  4815                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4816                              <1> 
  4817 000023B9 F687[196C0000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4818 000023C0 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4819 000023C2 D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4820                              <1> 
  4821 000023C4 3AAF[1D6C0000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4822 000023CA 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4823                              <1> 
  4824 000023CC BA[FF230000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4825 000023D1 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4826 000023D2 88AF[1D6C0000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4827 000023D8 B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4828 000023DA E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4829 000023DF 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4830 000023E1 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4831 000023E3 E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4832 000023E8 8AA7[1D6C0000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4833 000023EE E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4834 000023F3 E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4835                              <1> 
  4836                              <1> ;-----	WAIT FOR HEAD SETTLE
  4837                              <1> 
  4838                              <1> DO_WAIT:
  4839 000023F8 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE STATUS
  4840 000023F9 E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4841 000023FE 9D                  <1> 	POPFd	; 24/12/2021		; RESTORE STATUS
  4842                              <1> RB:
  4843                              <1> NEC_ERR:
  4844                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4845                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4846 000023FF C3                  <1> 	RETn				; RETURN TO CALLER
  4847                              <1> 
  4848                              <1> ;-------------------------------------------------------------------------------
  4849                              <1> ; RECAL
  4850                              <1> ;	RECALIBRATE DRIVE
  4851                              <1> ;
  4852                              <1> ; ON ENTRY:	DI = DRIVE #
  4853                              <1> ;
  4854                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4855                              <1> ;-------------------------------------------------------------------------------
  4856                              <1> RECAL:
  4857                              <1> 	;PUSH	CX
  4858                              <1> 	; 24/12/2021
  4859 00002400 51                  <1> 	push	ecx
  4860 00002401 B8[1D240000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4861 00002406 50                  <1> 	PUSH	eAX
  4862 00002407 B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4863 00002409 E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4864 0000240E 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4865 00002410 88DC                <1> 	MOV	AH,BL
  4866 00002412 E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4867 00002417 E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4868 0000241C 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4869                              <1> RC_BACK:
  4870                              <1> 	;POP	CX
  4871                              <1> 	; 24/12/2021
  4872 0000241D 59                  <1> 	pop	ecx
  4873 0000241E C3                  <1> 	RETn
  4874                              <1> 
  4875                              <1> ;-------------------------------------------------------------------------------
  4876                              <1> ; CHK_STAT_2
  4877                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4878                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4879                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4880                              <1> ;
  4881                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4882                              <1> ;-------------------------------------------------------------------------------
  4883                              <1> CHK_STAT_2:
  4884 0000241F B8[47240000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4885 00002424 50                  <1> 	PUSH	eAX
  4886 00002425 E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4887 0000242A 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4888 0000242C B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4889 0000242E E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4890 00002433 E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4891 00002438 720C                <1> 	JC	short J34
  4892 0000243A A0[0D6C0000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4893 0000243F 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4894 00002441 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4895 00002443 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4896 00002445 F8                  <1> 	CLC				; GOOD RETURN
  4897                              <1> J34:
  4898 00002446 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4899                              <1> CS_BACK:
  4900 00002447 C3                  <1> 	RETn
  4901                              <1> J35:
  4902 00002448 800D[0C6C0000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4903 0000244F F9                  <1> 	STC				; ERROR RETURN CODE
  4904 00002450 EBF4                <1> 	JMP	SHORT J34
  4905                              <1> 
  4906                              <1> ;-------------------------------------------------------------------------------
  4907                              <1> ; WAIT_INT
  4908                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4909                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4910                              <1> ;	IF THE DRIVE IS NOT READY.
  4911                              <1> ;
  4912                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4913                              <1> ;-------------------------------------------------------------------------------
  4914                              <1> 
  4915                              <1> ; 17/12/2014
  4916                              <1> ; 2.5 seconds waiting !
  4917                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4918                              <1> ; amount of time to wait for completion interrupt from NEC.
  4919                              <1> 
  4920                              <1> 
  4921                              <1> WAIT_INT:
  4922 00002452 FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4923 00002453 F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4924                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4925                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4926                              <1> 
  4927                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4928                              <1> 	;
  4929                              <1> 	;WAIT_FOR_MEM:	
  4930                              <1> 	;	Waits for a bit at a specified memory location pointed
  4931                              <1> 	;	to by ES:[DI] to become set.
  4932                              <1> 	;INPUT:
  4933                              <1> 	;	AH=Mask to test with.
  4934                              <1> 	;	ES:[DI] = memory location to watch.
  4935                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4936                              <1> 	;	     (normally 30 microseconds per period.)
  4937                              <1> 
  4938                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4939                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4940                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4941                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4942                              <1> 	; 27/02/2015
  4943 00002454 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4944                              <1> WFMS_CHECK_MEM:
  4945 00002459 F605[096C0000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4946 00002460 7516                <1>         jnz     short J37
  4947                              <1> WFMS_HI:
  4948 00002462 E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4949 00002464 A810                <1> 	TEST	AL,010H			; transition on memory
  4950 00002466 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4951                              <1> WFMS_LO:
  4952 00002468 E461                <1> 	IN	AL,PORT_B		;SYS1
  4953 0000246A A810                <1> 	TEST	AL,010H
  4954 0000246C 74FA                <1> 	JZ	SHORT WFMS_LO
  4955 0000246E E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4956                              <1> ;WFMS_OUTER_LP:
  4957                              <1> ;;	or	bl, bl			; check outer counter
  4958                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4959                              <1> ;	dec	bl
  4960                              <1> ;	jz	short J36A	
  4961                              <1> ;	jmp	short WFMS_CHECK_MEM
  4962                              <1> 
  4963                              <1> 	;17/12/2014
  4964                              <1> 	;16/12/2014
  4965                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4966                              <1> ;J36:
  4967                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4968                              <1> ;	JNZ	short J37
  4969                              <1> 	;16/12/2014
  4970                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4971                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4972                              <1> 	;JNZ	short J36
  4973                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4974                              <1> ;	jb	short J36
  4975                              <1> 
  4976                              <1> ;WFMS_TIMEOUT:
  4977                              <1> ;J36A:
  4978 00002470 800D[0C6C0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4979 00002477 F9                  <1> 	STC				; ERROR RETURN
  4980                              <1> J37:
  4981 00002478 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4982 00002479 8025[096C0000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4983 00002480 9D                  <1> 	POPF				; RECOVER CARRY
  4984 00002481 C3                  <1> 	RETn				; GOOD RETURN CODE
  4985                              <1> 
  4986                              <1> ;-------------------------------------------------------------------------------
  4987                              <1> ; RESULTS
  4988                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4989                              <1> ;	FOLLOWING AN INTERRUPT.
  4990                              <1> ;
  4991                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4992                              <1> ;		AX,BX,CX,DX DESTROYED
  4993                              <1> ;-------------------------------------------------------------------------------
  4994                              <1> RESULTS:
  4995 00002482 57                  <1> 	PUSH	eDI
  4996 00002483 BF[0D6C0000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4997 00002488 B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  4998 0000248A 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4999                              <1> 
  5000                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  5001                              <1> 
  5002                              <1> _R10: 
  5003                              <1> 	; 16/12/2014
  5004                              <1> 	; wait for (max) 0.5 seconds
  5005                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  5006                              <1> 	;XOR	CX,CX			; COUNTER
  5007                              <1> 
  5008                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  5009                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  5010                              <1> 	; 27/02/2015
  5011 0000248E B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  5012                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  5013                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  5014                              <1> 
  5015                              <1> WFPSR_OUTER_LP:
  5016                              <1> 	;
  5017                              <1> WFPSR_CHECK_PORT:
  5018                              <1> J39:					; WAIT FOR MASTER
  5019 00002493 EC                  <1> 	IN	AL,DX			; GET STATUS
  5020 00002494 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5021 00002496 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5022 00002498 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  5023                              <1> WFPSR_HI:
  5024 0000249A E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  5025 0000249C A810                <1> 	TEST	AL,010H			; transition on memory
  5026 0000249E 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  5027                              <1> WFPSR_LO:
  5028 000024A0 E461                <1> 	IN	AL, PORT_B		; SYS1
  5029 000024A2 A810                <1> 	TEST	AL,010H
  5030 000024A4 74FA                <1> 	JZ	SHORT WFPSR_LO
  5031 000024A6 E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  5032                              <1> 	;; 27/02/2015
  5033                              <1> 	;;dec	bh
  5034                              <1> 	;;jnz	short WFPSR_OUTER_LP
  5035                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  5036                              <1> 
  5037                              <1> 	;;mov	byte [wait_count], 0
  5038                              <1> ;J39:					; WAIT FOR MASTER
  5039                              <1> ;	IN	AL,DX			; GET STATUS
  5040                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5041                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5042                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  5043                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  5044                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  5045                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  5046                              <1> 	;
  5047                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  5048                              <1> 	;;jb	short J39	
  5049                              <1> 
  5050                              <1> ;WFPSR_TIMEOUT:
  5051 000024A8 800D[0C6C0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  5052 000024AF F9                  <1> 	STC				; SET ERROR RETURN
  5053 000024B0 EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  5054                              <1> 
  5055                              <1> ;-----	READ IN THE STATUS
  5056                              <1> 
  5057                              <1> J42:
  5058 000024B2 EB00                <1> 	JMP	$+2			; I/O DELAY
  5059 000024B4 6642                <1> 	INC	DX			; POINT AT DATA PORT
  5060 000024B6 EC                  <1> 	IN	AL,DX			; GET THE DATA
  5061                              <1> 	; 16/12/2014
  5062                              <1> 	NEWIODELAY
  2158 000024B7 E6EB                <2>  out 0EBh,al
  5063 000024B9 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  5064 000024BB 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  5065                              <1> 	; 16/12/2014
  5066                              <1> ;	push	cx
  5067                              <1> ;	mov	cx, 30
  5068                              <1> ;wdw2:
  5069                              <1> ;	NEWIODELAY
  5070                              <1> ;	loop	wdw2
  5071                              <1> ;	pop	cx
  5072                              <1> 
  5073 000024BC B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  5074 000024C1 E8F6EFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  5075 000024C6 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  5076 000024C8 EC                  <1> 	IN	AL,DX			; GET STATUS
  5077                              <1> 	; 16/12/2014
  5078                              <1> 	NEWIODELAY
  2158 000024C9 E6EB                <2>  out 0EBh,al
  5079                              <1> 	;
  5080 000024CB A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  5081 000024CD 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  5082                              <1> 
  5083 000024CF FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  5084 000024D1 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  5085 000024D3 800D[0C6C0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  5086 000024DA F9                  <1> 	STC				; SET ERROR FLAG
  5087                              <1> 
  5088                              <1> ;-----	RESULT OPERATION IS DONE
  5089                              <1> POPRES:
  5090 000024DB 5F                  <1> 	POP	eDI
  5091 000024DC C3                  <1> 	RETn				; RETURN WITH CARRY SET
  5092                              <1> 
  5093                              <1> ;-------------------------------------------------------------------------------
  5094                              <1> ; READ_DSKCHNG
  5095                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  5096                              <1> ;
  5097                              <1> ; ON ENTRY:	DI = DRIVE #
  5098                              <1> ;
  5099                              <1> ; ON EXIT:	DI = DRIVE #
  5100                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  5101                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  5102                              <1> ;		AX,CX,DX DESTROYED
  5103                              <1> ;-------------------------------------------------------------------------------
  5104                              <1> READ_DSKCHNG:
  5105 000024DD E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  5106 000024E2 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  5107 000024E6 EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  5108 000024E7 A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5109 000024E9 C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5110                              <1> 
  5111                              <1> ;-------------------------------------------------------------------------------
  5112                              <1> ; DRIVE_DET
  5113                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5114                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5115                              <1> ; ON ENTRY:	DI = DRIVE #
  5116                              <1> ;-------------------------------------------------------------------------------
  5117                              <1> DRIVE_DET:
  5118 000024EA E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5119 000024EF E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5120 000024F4 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5121 000024F6 B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5122 000024F8 E884FEFFFF          <1> 	CALL	SEEK
  5123 000024FD 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5124 000024FF B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5125                              <1> SK_GIN:
  5126 00002501 FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5127                              <1> 	;PUSH	CX			; SAVE TRACK
  5128                              <1> 	; 24/12/2021
  5129 00002503 51                  <1> 	push	ecx
  5130 00002504 E878FEFFFF          <1> 	CALL	SEEK
  5131 00002509 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5132 0000250B B8[46250000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5133 00002510 50                  <1> 	PUSH	eAX
  5134 00002511 B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5135 00002513 E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5136 00002518 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5137 0000251B 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5138 0000251D E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5139 00002522 E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5140 00002527 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5141                              <1> 	;POP	CX			; RESTORE TRACK
  5142                              <1> 	; 24/12/2021
  5143 00002528 59                  <1> 	pop	ecx
  5144 00002529 F605[0D6C0000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5145 00002530 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5146 00002532 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5147 00002534 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5148                              <1> 
  5149                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5150                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5151                              <1> 
  5152 00002536 808F[196C0000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5153 0000253D C3                  <1> 	RETn				; ALL INFORMATION SET
  5154                              <1> IS_80:
  5155 0000253E 808F[196C0000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5156                              <1> DD_BAC:
  5157 00002545 C3                  <1> 	RETn
  5158                              <1> POP_BAC:
  5159                              <1> 	;POP	CX			; THROW AWAY
  5160                              <1> 	; 24/12/2021
  5161 00002546 59                  <1> 	pop	ecx
  5162 00002547 C3                  <1> 	RETn
  5163                              <1> 
  5164                              <1> fdc_int:  
  5165                              <1> 	  ; 30/07/2015	
  5166                              <1> 	  ; 16/02/2015
  5167                              <1> ;int_0Eh: ; 11/12/2014
  5168                              <1> 
  5169                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5170                              <1> ; DISK_INT
  5171                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5172                              <1> ;
  5173                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5174                              <1> ;-------------------------------------------------------------------------------
  5175                              <1> DISK_INT_1:
  5176                              <1> 
  5177                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5178                              <1> 	; 24/12/2021
  5179 00002548 50                  <1> 	push	eax
  5180 00002549 1E                  <1> 	push	ds
  5181 0000254A 66B81000            <1> 	mov	ax, KDATA
  5182 0000254E 8ED8                <1> 	mov 	ds, ax
  5183 00002550 800D[096C0000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5184 00002557 B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5185 00002559 E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5186 0000255B 1F                  <1> 	pop	ds
  5187                              <1> 	;POP	AX			; RECOVER REGISTER
  5188                              <1> 	; 24/12/2021
  5189 0000255C 58                  <1> 	pop	eax
  5190 0000255D CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5191                              <1> 
  5192                              <1> ;-------------------------------------------------------------------------------
  5193                              <1> ; DSKETTE_SETUP
  5194                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5195                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5196                              <1> ;-------------------------------------------------------------------------------
  5197                              <1> DSKETTE_SETUP:
  5198                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5199                              <1> 	;PUSH	BX
  5200                              <1> 	;PUSH	CX
  5201 0000255E 52                  <1> 	PUSH	eDX
  5202                              <1> 	;PUSH	DI
  5203                              <1> 	;;PUSH	DS
  5204                              <1> 	; 14/12/2014
  5205                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5206                              <1> 	;mov	[DISK_POINTER+2], cs
  5207                              <1> 	;
  5208                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5209 0000255F 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5210 00002561 66C705[196C0000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5210 00002569 00                  <1>
  5211 0000256A 8025[146C0000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5212 00002571 800D[146C0000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5213 00002578 C605[096C0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5214 0000257F C605[0B6C0000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5215 00002586 C605[0A6C0000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5216 0000258D C605[0C6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5217                              <1> 	;
  5218                              <1> 	; 28/02/2015
  5219                              <1> 	;mov	word [cfd], 100h 
  5220 00002594 E89DF2FFFF          <1> 	call	DSK_RESET
  5221 00002599 5A                  <1> 	pop	edx
  5222 0000259A C3                  <1> 	retn
  5223                              <1> 
  5224                              <1> ;SUP0:
  5225                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5226                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5227                              <1> ;	; 02/01/2015
  5228                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5229                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5230                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5231                              <1> ;       cmp     byte [fd1_type], 0	
  5232                              <1> ;	jna	short sup1
  5233                              <1> ;	or	di, di
  5234                              <1> ;	jnz	short sup1
  5235                              <1> ;	inc	di
  5236                              <1> ;       jmp     short SUP0
  5237                              <1> ;sup1:
  5238                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5239                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5240                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5241                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5242                              <1> ;	;POP	DI
  5243                              <1> ;	POP	eDX
  5244                              <1> ;	;POP	CX
  5245                              <1> ;	;POP	BX
  5246                              <1> ;	;POP	AX
  5247                              <1> ;	RETn
  5248                              <1> 
  5249                              <1> ;//////////////////////////////////////////////////////
  5250                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5251                              <1> ;
  5252                              <1> 
  5253                              <1> int13h: ; 21/02/2015
  5254 0000259B 9C                  <1> 	pushfd
  5255 0000259C 0E                  <1> 	push 	cs
  5256 0000259D E859000000          <1> 	call 	DISK_IO
  5257 000025A2 C3                  <1> 	retn
  5258                              <1> 
  5259                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5260                              <1> ;/////////////////////////////////////////////////////////////////////
  5261                              <1> 
  5262                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5263                              <1> ; 23/02/2015
  5264                              <1> ; 21/02/2015 (unix386.s)
  5265                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5266                              <1> ;
  5267                              <1> ; Original Source Code:
  5268                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5269                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5270                              <1> ;
  5271                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5272                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5273                              <1> ;
  5274                              <1> 
  5275                              <1> ;The wait for controller to be not busy is 10 seconds.
  5276                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5277                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5278                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5279                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5280                              <1> 
  5281                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5282                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5283                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5284                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5285                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5286                              <1> 
  5287                              <1> ;The wait for Data request on read and write longs is
  5288                              <1> ;2000 us. (?)
  5289                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5290                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5291                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5292                              <1> 
  5293                              <1> ; Port 61h (PORT_B)
  5294                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5295                              <1> 
  5296                              <1> ; 23/12/2014
  5297                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5298                              <1> 
  5299                              <1> ;--- INT 13H -------------------------------------------------------------------
  5300                              <1> ;									       :
  5301                              <1> ; FIXED DISK I/O INTERFACE						       :
  5302                              <1> ;									       :
  5303                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5304                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5305                              <1> ;									       :
  5306                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5307                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5308                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5309                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5310                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5311                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5312                              <1> ;									       :
  5313                              <1> ;------------------------------------------------------------------------------:
  5314                              <1> ;									       :
  5315                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5316                              <1> ;									       :
  5317                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5318                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5319                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5320                              <1> ;			  DL > 80H - DISK				       :
  5321                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5322                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5323                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5324                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5325                              <1> ;	(AH)= 06H  UNUSED						       :
  5326                              <1> ;	(AH)= 07H  UNUSED						       :
  5327                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5328                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5329                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5330                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5331                              <1> ;	(AH)= 0AH  READ LONG						       :
  5332                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5333                              <1> ;	(AH)= 0CH  SEEK 						       :
  5334                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5335                              <1> ;	(AH)= 0EH  UNUSED						       :
  5336                              <1> ;	(AH)= 0FH  UNUSED						       :
  5337                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5338                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5339                              <1> ;	(AH)= 12H  UNUSED						       :
  5340                              <1> ;	(AH)= 13H  UNUSED						       :
  5341                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5342                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5343                              <1> ;									       :
  5344                              <1> ;-------------------------------------------------------------------------------
  5345                              <1> ;									       :
  5346                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5347                              <1> ;									       :
  5348                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5349                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5350                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5351                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5352                              <1> ;									       :
  5353                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5354                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5355                              <1> ;				 (10 BITS TOTAL)			       :
  5356                              <1> ;									       :
  5357                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5358                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5359                              <1> ;									       :
  5360                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5361                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5362                              <1> ;									       :
  5363                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5364                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5365                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5366                              <1> ;			       80H FOR A BAD SECTOR			       :
  5367                              <1> ;			   N = SECTOR NUMBER				       :
  5368                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5369                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5370                              <1> ;									       :
  5371                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5372                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5373                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5374                              <1> ;									       :
  5375                              <1> ;-------------------------------------------------------------------------------
  5376                              <1> 
  5377                              <1> ;-------------------------------------------------------------------------------
  5378                              <1> ; OUTPUT								       :
  5379                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5380                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5381                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5382                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5383                              <1> ;									       :
  5384                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5385                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5386                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5387                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5388                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5389                              <1> ;		REWRITTEN.						       :
  5390                              <1> ;									       :
  5391                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5392                              <1> ;	   INPUT:							       :
  5393                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5394                              <1> ;	   OUTPUT:							       :
  5395                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5396                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5397                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5398                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5399                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5400                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5401                              <1> ;									       :
  5402                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5403                              <1> ;									       :
  5404                              <1> ;	AH = 0 - NOT PRESENT						       :
  5405                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5406                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5407                              <1> ;	     3 - FIXED DISK						       :
  5408                              <1> ;									       :
  5409                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5410                              <1> ;									       :
  5411                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5412                              <1> ;	INFORMATION.							       :
  5413                              <1> ;									       :
  5414                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5415                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5416                              <1> ;									       :
  5417                              <1> ;-------------------------------------------------------------------------------
  5418                              <1> 
  5419                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5420                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5421                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5422                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5423                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5424                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5425                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5426                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5427                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5428                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5429                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5430                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5431                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5432                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5433                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5434                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5435                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5436                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5437                              <1> 
  5438                              <1> ;--------------------------------------------------------
  5439                              <1> ;							:
  5440                              <1> ; FIXED DISK PARAMETER TABLE				:
  5441                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5442                              <1> ;							:
  5443                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5444                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5445                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5446                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5447                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5448                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5449                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5450                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5451                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5452                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5453                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5454                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5455                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5456                              <1> ;							:
  5457                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5458                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5459                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5460                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5461                              <1> ;							:
  5462                              <1> ;--------------------------------------------------------
  5463                              <1> 
  5464                              <1> ;--------------------------------------------------------
  5465                              <1> ;							:
  5466                              <1> ; HARDWARE SPECIFIC VALUES				:
  5467                              <1> ;							:
  5468                              <1> ;  -  CONTROLLER I/O PORT				:
  5469                              <1> ;							:
  5470                              <1> ;     > WHEN READ FROM: 				:
  5471                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5472                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5473                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5474                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5475                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5476                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5477                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5478                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5479                              <1> ;							:
  5480                              <1> ;     > WHEN WRITTEN TO:				:
  5481                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5482                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5483                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5484                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5485                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5486                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5487                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5488                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5489                              <1> ;							:
  5490                              <1> ;--------------------------------------------------------
  5491                              <1> 
  5492                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5493                              <1> ;HF1_PORT	equ	0170h	
  5494                              <1> ;HF_REG_PORT	EQU	03F6H
  5495                              <1> ;HF1_REG_PORT	equ	0376h
  5496                              <1> 
  5497                              <1> HDC1_BASEPORT	equ	1F0h
  5498                              <1> HDC2_BASEPORT	equ	170h		
  5499                              <1> 
  5500 000025A3 90                  <1> align 2
  5501                              <1> 
  5502                              <1> ;-----		STATUS REGISTER
  5503                              <1> 
  5504                              <1> ST_ERROR	EQU	00000001B	;
  5505                              <1> ST_INDEX	EQU	00000010B	;
  5506                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5507                              <1> ST_DRQ		EQU	00001000B	;
  5508                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5509                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5510                              <1> ST_READY	EQU	01000000B	;
  5511                              <1> ST_BUSY 	EQU	10000000B	;
  5512                              <1> 
  5513                              <1> ;-----		ERROR REGISTER
  5514                              <1> 
  5515                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5516                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5517                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5518                              <1> ;		EQU	00001000B	; NOT USED
  5519                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5520                              <1> ;		EQU	00100000B	; NOT USED
  5521                              <1> ERR_DATA_ECC	EQU	01000000B
  5522                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5523                              <1> 
  5524                              <1> 
  5525                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5526                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5527                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5528                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5529                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5530                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5531                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5532                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5533                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5534                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5535                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5536                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5537                              <1> 
  5538                              <1> ;MAX_FILE	EQU	2
  5539                              <1> ;S_MAX_FILE	EQU	2
  5540                              <1> MAX_FILE	equ	4		; 22/12/2014
  5541                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5542                              <1> 
  5543                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5544                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5545                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5546                              <1> 
  5547                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5548                              <1> 
  5549                              <1> ;-----		COMMAND BLOCK REFERENCE
  5550                              <1> 
  5551                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5552                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5553                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5554                              <1> ; 19/12/2014
  5555                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5556                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5557                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5558                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5559                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5560                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5561                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5562                              <1> 
  5563                              <1> align 2
  5564                              <1> 
  5565                              <1> ;----------------------------------------------------------------
  5566                              <1> ; FIXED DISK I/O SETUP						:
  5567                              <1> ;								:
  5568                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5569                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5570                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5571                              <1> ;								:
  5572                              <1> ;----------------------------------------------------------------
  5573                              <1> 
  5574                              <1> DISK_SETUP:
  5575                              <1> 	;CLI
  5576                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5577                              <1> 	;xor	ax,ax
  5578                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5579                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5580                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5581                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5582                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5583                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5584                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5585                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5586                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5587                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5588                              <1> 	;;MOV	[HDISK_INT+2],CS
  5589                              <1> 	;mov	[HDISK_INT1+2],CS
  5590                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5591                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5592                              <1> 	;mov	[HDISK_INT2+2],CS
  5593                              <1> 	;
  5594                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5595                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5596                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5597                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5598                              <1> 	;push	cs
  5599                              <1> 	;pop	ds
  5600                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5601                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5602 000025A4 C705[246C0000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5602 000025AC 0900                <1>
  5603                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5604                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5605 000025AE C705[286C0000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5605 000025B6 0900                <1>
  5606                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5607                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5608 000025B8 C705[2C6C0000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5608 000025C0 0900                <1>
  5609                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5610                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5611 000025C2 C705[306C0000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5611 000025CA 0900                <1>
  5612                              <1> 	;
  5613                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5614                              <1> 	;;;AND	AL,0BFH
  5615                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5616                              <1> 	;;;JMP	$+2
  5617                              <1> 	;;IODELAY
  5618                              <1> 	;;OUT	INTB01,AL
  5619                              <1> 	;;IODELAY
  5620                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5621                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5622                              <1> 	;;;JMP	$+2
  5623                              <1> 	;;IODELAY
  5624                              <1> 	;;OUT	INTA01,AL
  5625                              <1> 	;
  5626                              <1> 	;STI
  5627                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5628                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5629                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5630                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5631                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5632                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5633                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5634                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5635                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5636                              <1> 	;mov	si, hd0_type
  5637 000025CC BE[80660000]        <1> 	mov	esi, hd0_type
  5638                              <1> 	;mov	cx, 4
  5639 000025D1 B904000000          <1> 	mov	ecx, 4
  5640                              <1> hde_l:
  5641 000025D6 AC                  <1> 	lodsb
  5642 000025D7 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5643 000025D9 7206                <1> 	jb	short _L4
  5644 000025DB FE05[206C0000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5645                              <1> _L4: ; 26/02/2015
  5646 000025E1 E2F3                <1> 	loop	hde_l	
  5647                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5648                              <1> ;L4:
  5649                              <1> 	; 
  5650                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5651                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5652                              <1> 	;;mov 	cl, 3
  5653                              <1> 	;;
  5654                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5655                              <1> ;;hdc_dl:
  5656                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5657                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5658                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5659                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5660                              <1> 	;;jnc	short hdc_reset0
  5661                              <1> 	;;loop	hdc_dl
  5662                              <1> 	;;; 27/12/2014
  5663                              <1> 	;;stc
  5664                              <1> 	;;retn
  5665                              <1> 	;
  5666                              <1> ;;hdc_reset0:
  5667                              <1> 	; 18/01/2015
  5668 000025E3 8A0D[206C0000]      <1> 	mov	cl, [HF_NUM]
  5669 000025E9 20C9                <1> 	and	cl, cl
  5670 000025EB 740D                <1> 	jz	short POD_DONE
  5671                              <1> 	;
  5672 000025ED B27F                <1> 	mov	dl, 7Fh
  5673                              <1> hdc_reset1:
  5674 000025EF FEC2                <1> 	inc	dl
  5675                              <1> 	;; 31/12/2015
  5676                              <1> 	;;push	dx
  5677                              <1> 	;;push	cx
  5678                              <1> 	;;push	ds
  5679                              <1> 	;;sub	ax, ax
  5680                              <1> 	;;mov	ds, ax
  5681                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5682                              <1> 	;;pop	ds
  5683                              <1> 	;;MOV	BX,AX
  5684                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5685                              <1> 	;;MOV	CX,AX
  5686                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5687                              <1> 	;;
  5688                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5689                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5690                              <1> 	;;pop	cx
  5691                              <1> 	;;pop	dx
  5692                              <1> 	;;
  5693                              <1> 	; 18/01/2015
  5694 000025F1 B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5695                              <1> 	;int	13h
  5696 000025F3 E8A3FFFFFF          <1> 	call	int13h
  5697 000025F8 E2F5                <1> 	loop	hdc_reset1
  5698                              <1> POD_DONE:
  5699 000025FA C3                  <1> 	RETn
  5700                              <1> 
  5701                              <1> ;;-----	POD_ERROR
  5702                              <1> 
  5703                              <1> ;;CTL_ERRX:
  5704                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5705                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5706                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5707                              <1> ;	;JMP	short POD_DONE
  5708                              <1> 
  5709                              <1> ;;HD_RESET_1:
  5710                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5711                              <1> ;;	;PUSH	CX
  5712                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5713                              <1> ;;	INT	13H
  5714                              <1> ;;	JC	short RES_2
  5715                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5716                              <1> ;;	INT	13H
  5717                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5718                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5719                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5720                              <1> ;;					; (30 seconds)		
  5721                              <1> ;;	;cmc
  5722                              <1> ;;	;JNC	short RES_1
  5723                              <1> ;;	jb	short RES_1
  5724                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5725                              <1> ;;	;TEST	DL,1
  5726                              <1> ;;	;JNZ	RES_E1
  5727                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5728                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5729                              <1> ;;	;JMP	SHORT RES_E1
  5730                              <1> ;;RES_ER: ; 22/12/2014
  5731                              <1> ;;RES_OK:
  5732                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5733                              <1> ;;	;POP	BX
  5734                              <1> ;;	RETn
  5735                              <1> ;;
  5736                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5737                              <1> ;;	INT	13H
  5738                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5739                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5740                              <1> ;;	INT	13H
  5741                              <1> ;;	JC	short RES_ER
  5742                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5743                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5744                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5745                              <1> ;;	INT	13H
  5746                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5747                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5748                              <1> ;;	JE	short RES_OK
  5749                              <1> ;;	CMP	AH,DATA_CORRECTED
  5750                              <1> ;;	JE	short RES_OK
  5751                              <1> ;;	CMP	AH,BAD_ECC
  5752                              <1> ;;	JE	short RES_OK
  5753                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5754                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5755                              <1> ;;					; (60 seconds)		
  5756                              <1> ;;	cmc
  5757                              <1> ;;	JC	short RES_ER		; FAILED
  5758                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5759                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5760                              <1> ;;	AND	AL,3FH
  5761                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5762                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5763                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5764                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5765                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5766                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5767                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5768                              <1> ;;	;TEST	DL,1
  5769                              <1> ;;	;JNZ	short RES_E1
  5770                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5771                              <1> ;;;RES_E1:
  5772                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5773                              <1> ;;;RES_OK:
  5774                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5775                              <1> ;;	;POP	BX
  5776                              <1> ;;	;RETn
  5777                              <1> ;
  5778                              <1> ;;SET_FAIL:
  5779                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5780                              <1> ;	;CALL	CMOS_READ
  5781                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5782                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5783                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5784                              <1> ;	;RETn
  5785                              <1> ;
  5786                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5787                              <1> ;	;POP	AX			; SAVE RETURN
  5788                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5789                              <1> ;	;POP	BX
  5790                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5791                              <1> ;	;PUSH	CX
  5792                              <1> ;	;PUSH	AX
  5793                              <1> ;	;push	ds
  5794                              <1> ;	;xor	ax, ax
  5795                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5796                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5797                              <1> ;	;				; BX = START TIME
  5798                              <1> ;	;				; CX = END TIME
  5799                              <1> ;	;pop	ds
  5800                              <1> ;	;CMP	BX,CX
  5801                              <1> ;	;JB	short TCHK1		; START < END
  5802                              <1> ;	;CMP	BX,AX
  5803                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5804                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5805                              <1> ;;TCHK1: CMP	AX,BX
  5806                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5807                              <1> ;;TCHK2: CMP	AX,CX
  5808                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5809                              <1> ;;					; OR CURRENT < END < START
  5810                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5811                              <1> ;;	RETn
  5812                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5813                              <1> ;;	RETn
  5814                              <1> ;;
  5815                              <1> ;;int_13h:
  5816                              <1> 
  5817                              <1> ;----------------------------------------
  5818                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5819                              <1> ;----------------------------------------
  5820                              <1> 
  5821                              <1> DISK_IO:
  5822 000025FB 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5823                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5824                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5825                              <1> 	;;call	int40h
  5826                              <1> 	;jb	DISKETTE_IO_1
  5827                              <1> 	; 24/12/2021
  5828 000025FE 7305                <1> 	jnb	short A1
  5829 00002600 E95FF1FFFF          <1> 	jmp	DISKETTE_IO_1
  5830                              <1> ;RET_2:
  5831                              <1> 	;RETf	2			; BACK TO CALLER
  5832                              <1> ;	retf	4
  5833                              <1> A1:
  5834 00002605 FB                  <1> 	STI				; ENABLE INTERRUPTS
  5835                              <1> 	;; 04/01/2015
  5836                              <1> 	;;OR	AH,AH
  5837                              <1> 	;;JNZ	short A2
  5838                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5839                              <1> 	;;SUB	AH,AH
  5840 00002606 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5841 00002609 772E                <1> 	JA	short RET_2
  5842                              <1> 	; 18/01/2015
  5843 0000260B 08E4                <1> 	or	ah,ah
  5844 0000260D 742D                <1> 	jz	short A4
  5845 0000260F 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5846 00002612 7504                <1> 	jne	short A2
  5847 00002614 28E4                <1> 	sub	ah,ah	; Reset
  5848 00002616 EB24                <1> 	jmp	short A4
  5849                              <1> A2:
  5850 00002618 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5851                              <1> 	;JNZ	short A3
  5852                              <1>         ;JMP    GET_PARM_N
  5853                              <1> 	;je	GET_PARM_N
  5854                              <1> 	; 24/12/2021
  5855 0000261B 7505                <1> 	jne	short A3
  5856 0000261D E90D030000          <1> 	jmp	GET_PARM_N
  5857                              <1> A3:	
  5858 00002622 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5859                              <1> 	;JNZ	short A4
  5860                              <1>         ;JMP    READ_DASD_TYPE
  5861                              <1> 	;je	READ_DASD_TYPE
  5862                              <1> 	; 24/12/2021
  5863 00002625 7505                <1> 	jne	short A3_A4
  5864 00002627 E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5865                              <1> A3_A4:
  5866                              <1> 	; 02/02/2015
  5867 0000262C 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5868                              <1> 	; 12/01/2015
  5869 0000262F F5                  <1> 	cmc
  5870 00002630 730A                <1> 	jnc	short A4
  5871                              <1> 	; 30/01/2015
  5872                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5873 00002632 C605[1F6C0000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5874                              <1> 	;jmp	short RET_2
  5875                              <1> RET_2:
  5876 00002639 CA0400              <1> 	retf	4
  5877                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5878 0000263C C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5879 00002640 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5880 00002641 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5881 00002642 52                  <1> 	PUSH	eDX
  5882 00002643 1E                  <1> 	PUSH	DS
  5883 00002644 06                  <1> 	PUSH	ES
  5884 00002645 56                  <1> 	PUSH	eSI
  5885 00002646 57                  <1> 	PUSH	eDI
  5886                              <1> 	;;04/01/2015
  5887                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5888                              <1> 	;;JNZ	short A5
  5889                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5890                              <1> ;;A5:	
  5891                              <1> 	;push	cs
  5892                              <1> 	;pop	ds
  5893                              <1> 	; 21/02/2015
  5894                              <1> 	;push	ax
  5895                              <1> 	; 24/12/2021
  5896 00002647 50                  <1> 	push	eax
  5897 00002648 66B81000            <1> 	mov	ax, KDATA
  5898 0000264C 8ED8                <1> 	mov	ds, ax
  5899 0000264E 8EC0                <1> 	mov	es, ax	
  5900                              <1> 	;pop	ax
  5901                              <1> 	; 24/12/2021
  5902 00002650 58                  <1> 	pop	eax
  5903 00002651 E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5904                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5905 00002656 8A25[1F6C0000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5906 0000265C 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5907 0000265F F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5908 00002660 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5909 00002661 5E                  <1> 	POP	eSI
  5910 00002662 07                  <1>         POP     ES
  5911 00002663 1F                  <1>         POP     DS
  5912 00002664 5A                  <1> 	POP	eDX
  5913 00002665 59                  <1> 	POP	eCX
  5914 00002666 5B                  <1> 	POP	eBX
  5915 00002667 C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5916                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5917 00002668 CA0400              <1> 	retf	4
  5918                              <1> ; 21/02/2015
  5919                              <1> ;       dw --> dd
  5920                              <1> M1:					; FUNCTION TRANSFER TABLE
  5921 0000266B [24280000]          <1> 	dd	DISK_RESET		; 000H
  5922 0000266F [99280000]          <1> 	dd	RETURN_STATUS		; 001H
  5923 00002673 [A6280000]          <1> 	dd	DISK_READ		; 002H
  5924 00002677 [AF280000]          <1> 	dd	DISK_WRITE		; 003H
  5925 0000267B [B8280000]          <1> 	dd	DISK_VERF		; 004H
  5926 0000267F [D0280000]          <1> 	dd	FMT_TRK 		; 005H
  5927 00002683 [1A280000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5928 00002687 [1A280000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5929 0000268B [1A280000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5930 0000268F [91290000]          <1> 	dd	INIT_DRV		; 009H
  5931 00002693 [F0290000]          <1> 	dd	RD_LONG 		; 00AH
  5932 00002697 [F9290000]          <1> 	dd	WR_LONG 		; 00BH
  5933 0000269B [022A0000]          <1> 	dd	DISK_SEEK		; 00CH
  5934 0000269F [24280000]          <1> 	dd	DISK_RESET		; 00DH
  5935 000026A3 [1A280000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5936 000026A7 [1A280000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5937 000026AB [2A2A0000]          <1> 	dd	TST_RDY 		; 010H
  5938 000026AF [4E2A0000]          <1> 	dd	HDISK_RECAL		; 011H
  5939 000026B3 [1A280000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5940 000026B7 [1A280000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5941 000026BB [842A0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5942                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5943 000026BF [1A280000]          <1> 	dd	BAD_COMMAND		; 015h
  5944 000026C3 [1A280000]          <1> 	dd	BAD_COMMAND		; 016h
  5945 000026C7 [1A280000]          <1> 	dd	BAD_COMMAND		; 017h
  5946 000026CB [1A280000]          <1> 	dd	BAD_COMMAND		; 018h
  5947 000026CF [1A280000]          <1> 	dd	BAD_COMMAND		; 019h
  5948 000026D3 [1A280000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5949 000026D7 [A6280000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5950 000026DB [AF280000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5951                              <1> M1L     EQU    $-M1
  5952                              <1> 
  5953                              <1> DISK_IO_CONT:
  5954                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5955 000026DF 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5956                              <1> 	;;JNZ	short SU0
  5957                              <1>         ;;JMP	RETURN_STATUS
  5958                              <1> 	;je	RETURN_STATUS
  5959                              <1> 	; 24/12/2021
  5960 000026E2 7505                <1> 	jne	short SU0
  5961 000026E4 E9B0010000          <1> 	jmp	RETURN_STATUS
  5962                              <1> SU0:
  5963 000026E9 C605[1F6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5964                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5965                              <1> 	;mov	si, bx ;; 14/02/2015
  5966 000026F0 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5967 000026F2 8A1D[206C0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5968                              <1> 	;; 04/01/2015
  5969                              <1> 	;;PUSH	AX
  5970 000026F8 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5971                              <1> 					; (get drive number as 0 to 3)
  5972 000026FB 38D3                <1> 	CMP	BL,DL
  5973                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5974                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5975                              <1> 	; 24/12/2021
  5976 000026FD 7705                <1> 	ja	short su0_su1
  5977 000026FF E916010000          <1> 	jmp	BAD_COMMAND
  5978                              <1> su0_su1:
  5979                              <1>         ;;03/01/2015
  5980 00002704 29DB                <1> 	sub	ebx, ebx
  5981 00002706 88D3                <1> 	mov	bl, dl
  5982                              <1> 	;sub	bh, bh
  5983 00002708 883D[346C0000]      <1> 	mov	[LBAMode], bh 	; 0
  5984                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5985                              <1> 	;test	byte [ebx+hd0_type], 1
  5986                              <1> 	;jz	short su1		; no
  5987                              <1> 	;inc	byte [LBAMode]
  5988                              <1> ;su1:
  5989                              <1> 	; 21/02/2015 (32 bit modification)
  5990                              <1> 	; 04/01/2015
  5991                              <1> 	;push	ax ; ***
  5992                              <1> 	; 24/12/2021
  5993 0000270E 50                  <1> 	push	eax ; ***
  5994                              <1> 	;PUSH	ES ; **
  5995                              <1> 	;PUSH	DX ; *
  5996                              <1> 	; 24/12/2021
  5997 0000270F 52                  <1> 	push	edx ; *
  5998                              <1> 	;push	ax
  5999 00002710 50                  <1> 	push	eax
  6000 00002711 E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  6001                              <1> 	; 02/02/2015
  6002                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  6003 00002716 668B4310            <1> 	mov	ax, [ebx+16]
  6004 0000271A 66A3[74660000]      <1> 	mov	[HF_PORT], ax
  6005                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  6006 00002720 668B5312            <1> 	mov	dx, [ebx+18]
  6007 00002724 668915[76660000]    <1> 	mov	[HF_REG_PORT], dx
  6008                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  6009 0000272B 8A4314              <1> 	mov	al, [ebx+20]
  6010                              <1> 	; 23/02/2015
  6011 0000272E A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  6012 00002730 7406                <1> 	jz 	short su1
  6013 00002732 FE05[346C0000]      <1> 	inc	byte [LBAMode] ; 1 
  6014                              <1> su1: 	 
  6015 00002738 C0E804              <1> 	shr 	al, 4
  6016 0000273B 2401                <1> 	and	al, 1			
  6017 0000273D A2[78660000]        <1> 	mov	[hf_m_s], al 
  6018                              <1> 	;
  6019                              <1> 	; 03/01/2015
  6020                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  6021 00002742 8A4308              <1> 	mov	al, [ebx+8]
  6022                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  6023 00002745 EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  6024                              <1> 					; Control Byte:  (= 08h, here)
  6025                              <1> 					; bit 0 - 0
  6026                              <1> 					; bit 1 - nIEN (1 = disable irq)
  6027                              <1> 					; bit 2 - SRST (software RESET)
  6028                              <1> 					; bit 3 - use extra heads (8 to 15)
  6029                              <1> 					;         -always set to 1-	
  6030                              <1> 					; (bits 3 to 7 are reserved
  6031                              <1> 					;          for ATA devices)
  6032 00002746 8A25[216C0000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6033 0000274C 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  6034 0000274F 08C4                <1> 	OR	AH,AL
  6035 00002751 8825[216C0000]      <1> 	MOV	[CONTROL_BYTE],AH	
  6036                              <1> 	; 04/01/2015
  6037                              <1> 	;pop	ax
  6038                              <1> 	; 24/12/2021
  6039 00002757 58                  <1> 	pop	eax
  6040                              <1> 	;pop	dx ; * ;; 14/02/2015
  6041                              <1> 	; 24/12/2021
  6042 00002758 5A                  <1> 	pop	edx ; *
  6043 00002759 20E4                <1> 	and	ah, ah	; Reset function ?
  6044 0000275B 7506                <1> 	jnz	short su2
  6045                              <1> 	;;pop	dx ; * ;; 14/02/2015
  6046                              <1> 	;pop	es ; **
  6047                              <1> 	;pop	ax ; ***
  6048                              <1> 	; 24/12/2021
  6049 0000275D 58                  <1> 	pop	eax ; ***	
  6050                              <1> 	;;pop	bx
  6051 0000275E E9C1000000          <1>         jmp     DISK_RESET
  6052                              <1> su2:
  6053 00002763 803D[346C0000]00    <1> 	cmp	byte [LBAMode], 0
  6054 0000276A 765E                <1> 	jna	short su3
  6055                              <1> 	;
  6056                              <1> 	; 02/02/2015 (LBA read/write function calls)
  6057 0000276C 80FC1B              <1> 	cmp	ah, 1Bh
  6058 0000276F 720B                <1> 	jb	short lbarw1
  6059 00002771 80FC1C              <1> 	cmp	ah, 1Ch
  6060 00002774 7759                <1> 	ja 	short invldfnc
  6061                              <1> 	;;pop	dx ; * ; 14/02/2015
  6062                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  6063 00002776 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  6064                              <1> 	;; 14/02/2015
  6065 00002778 88D1                <1> 	mov	cl, dl ; 14/02/2015
  6066                              <1> 	;;mov	dx, bx
  6067                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  6068                              <1> 	;;mov	bx, di
  6069                              <1> 	;mov	si, di ; Buffer offset
  6070 0000277A EB2E                <1> 	jmp	short lbarw2
  6071                              <1> lbarw1:
  6072                              <1> 	; convert CHS to LBA
  6073                              <1> 	;
  6074                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  6075                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  6076                              <1> 	;	+ Sector - 1
  6077                              <1> 	;push	dx ; * ;; 14/02/2015
  6078                              <1> 	; 24/12/2021
  6079 0000277C 52                  <1> 	push	edx ; *
  6080                              <1> 	;xor	dh, dh
  6081 0000277D 31D2                <1> 	xor	edx, edx
  6082                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  6083 0000277F 8A530E              <1> 	mov	dl, [ebx+14]
  6084                              <1> 	;xor	ah, ah
  6085 00002782 31C0                <1> 	xor	eax, eax
  6086                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  6087 00002784 8A4302              <1> 	mov	al, [ebx+2]
  6088 00002787 FEC8                <1> 	dec	al
  6089                              <1> 	;inc	ax		; 0 =  256
  6090 00002789 40                  <1> 	inc	eax ; 24/12/2021
  6091 0000278A 66F7E2              <1> 	mul 	dx
  6092                              <1> 		; AX = # of Heads" * Sectors/Track
  6093 0000278D 6689CA              <1> 	mov	dx, cx
  6094                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  6095 00002790 83E13F              <1> 	and	ecx, 3fh
  6096 00002793 86D6                <1> 	xchg	dl, dh
  6097 00002795 C0EE06              <1> 	shr	dh, 6
  6098                              <1> 		; DX = cylinder (0 to 1023)
  6099                              <1> 	;mul 	dx
  6100                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  6101 00002798 F7E2                <1> 	mul	edx
  6102 0000279A FEC9                <1> 	dec	cl  ; sector - 1
  6103                              <1> 	;add	ax, cx
  6104                              <1> 	;adc	dx, 0
  6105                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  6106 0000279C 01C8                <1> 	add	eax, ecx
  6107                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  6108                              <1> 	; 24/12/2021
  6109 0000279E 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6110                              <1> 	;push	dx
  6111                              <1> 	;push	ax
  6112 0000279F 50                  <1> 	push	eax
  6113                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6114 000027A0 8A430E              <1> 	mov	al, [ebx+14]
  6115 000027A3 F6E5                <1> 	mul	ch
  6116                              <1> 		; AX = Head * Sectors/Track
  6117 000027A5 6699                <1>         cwd
  6118                              <1> 	;pop	dx
  6119 000027A7 5A                  <1> 	pop	edx
  6120                              <1> 	;add	ax, dx
  6121                              <1> 	;pop	dx
  6122                              <1> 	;adc	dx, 0 ; add carry bit
  6123 000027A8 01D0                <1> 	add	eax, edx
  6124                              <1> lbarw2:
  6125 000027AA 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6126 000027AC 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6127 000027AE C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6128                              <1> 				; NOTE: Features register (1F1h, 171h)
  6129                              <1> 				; is not used for ATA device R/W functions. 
  6130                              <1> 				; It is old/obsolete 'write precompensation'
  6131                              <1> 				; register and error register
  6132                              <1> 				; for old ATA/IDE devices.
  6133                              <1> 	; 18/01/2014
  6134                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6135 000027B2 8A0D[78660000]      <1> 	mov	cl, [hf_m_s]
  6136                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6137                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6138                              <1> 				; bit 6 = 1 = LBA mode
  6139                              <1> 				; bit 7 = 1
  6140 000027B8 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6141                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6142 000027BB 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6143 000027C0 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6144                              <1> 	;or	dh, ch
  6145 000027C3 09C8                <1> 	or	eax, ecx	
  6146                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6147                              <1> 				  ; (Sector Number Register)
  6148                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6149                              <1> 				  ; (Cylinder Low Register)
  6150                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6151                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6152                              <1> 				  ; (Cylinder High Register)
  6153                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6154                              <1> 				  ; (Drive/Head Register)
  6155                              <1> 	
  6156                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6157 000027C5 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6158                              <1> 	;14/02/2015
  6159                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6160 000027C8 EB37                <1> 	jmp	short su4
  6161                              <1> su3:
  6162                              <1> 	; 02/02/2015 
  6163                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6164 000027CA 80FC14              <1> 	cmp 	ah, 14h
  6165 000027CD 7603                <1> 	jna 	short chsfnc
  6166                              <1> invldfnc:
  6167                              <1>         ; 14/02/2015  
  6168                              <1> 	;pop	es ; **
  6169                              <1>         ;pop	ax ; ***
  6170                              <1>         ; 24/12/2021
  6171 000027CF 58                  <1> 	pop	eax ; ***
  6172                              <1> 	;jmp	short BAD_COMMAND_POP
  6173 000027D0 EB48                <1>         jmp     short BAD_COMMAND
  6174                              <1> chsfnc:	
  6175                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6176 000027D2 668B4305            <1> 	mov	ax, [ebx+5]
  6177 000027D6 66C1E802            <1> 	SHR	AX,2
  6178 000027DA 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6179                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6180                              <1> 	;;PUSH	DX
  6181                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6182                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6183                              <1> 	;;POP	DX ; * 
  6184                              <1> 	;;POP	ES ; **
  6185                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6186                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6187                              <1> 	;;OR	AH,AL
  6188                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6189                              <1> 	;
  6190 000027DD 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6191 000027DF 243F                <1> 	AND	AL,3FH
  6192 000027E1 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6193 000027E4 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6194 000027E7 88C8                <1> 	MOV	AL,CL
  6195 000027E9 C0E806              <1> 	SHR	AL,6
  6196 000027EC 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6197                              <1> 	;;05/01/2015
  6198                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6199 000027EF A0[78660000]        <1> 	mov	al, [hf_m_s]
  6200 000027F4 C0E004              <1> 	SHL	AL,4
  6201 000027F7 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6202 000027FA 08F0                <1> 	OR	AL,DH
  6203                              <1> 	;OR	AL,80H or 20H
  6204 000027FC 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6205 000027FE 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6206                              <1> su4:
  6207                              <1> 	;POP	ES ; **
  6208                              <1>         ;; 14/02/2015
  6209                              <1>         ;;POP   AX
  6210                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6211                              <1>         ;;PUSH  AX
  6212                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6213                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6214                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6215                              <1> 	;pop     ax ; ***
  6216                              <1> 	; 24/12/2021
  6217 00002801 58                  <1> 	pop	eax ; ***
  6218 00002802 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6219 00002805 29DB                <1>         sub	ebx, ebx
  6220 00002807 88E3                <1> 	mov     bl, ah
  6221                              <1>         ;xor	bh, bh
  6222                              <1>         ;sal	bx, 1
  6223 00002809 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6224                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6225                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6226                              <1>         ;;JNB   short BAD_COMMAND_POP
  6227                              <1>         ;cmp	bx, M1L
  6228 0000280D 83FB74              <1> 	cmp	ebx, M1L
  6229 00002810 7308                <1> 	jnb	short BAD_COMMAND
  6230                              <1>         ;xchg	bx, si
  6231 00002812 87DE                <1>         xchg	ebx, esi
  6232                              <1> 	;;;POP	AX			; RESTORE AX
  6233                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6234                              <1> 	
  6235                              <1> 	;;PUSH	CX
  6236                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6237                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6238                              <1> 	;SHR	CX,4
  6239                              <1> 	;MOV	AX,ES
  6240                              <1> 	;ADD	AX,CX
  6241                              <1> 	;MOV	ES,AX
  6242                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6243                              <1> 	;;POP	AX
  6244                              <1> 	;;POP	CX
  6245                              <1> 	;;JMP	word [CS:SI+M1]
  6246                              <1> 	;jmp	word [SI+M1]
  6247 00002814 FFA6[6B260000]      <1> 	jmp	dword [esi+M1]
  6248                              <1> ;;BAD_COMMAND_POP:
  6249                              <1> ;;	POP	AX
  6250                              <1> ;;	POP	BX
  6251                              <1> BAD_COMMAND:
  6252 0000281A C605[1F6C0000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6253 00002821 B000                <1> 	MOV	AL,0
  6254 00002823 C3                  <1> 	RETn
  6255                              <1> 
  6256                              <1> ;----------------------------------------
  6257                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6258                              <1> ;----------------------------------------
  6259                              <1> 
  6260                              <1> ; 18-1-2015 : one controller reset (not other one)
  6261                              <1> 
  6262                              <1> DISK_RESET:
  6263 00002824 FA                  <1> 	CLI
  6264 00002825 E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6265                              <1> 	;JMP	$+2
  6266                              <1> 	IODELAY
  2153 00002827 EB00                <2>  jmp short $+2
  2154 00002829 EB00                <2>  jmp short $+2
  6267                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6268 0000282B 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6269 0000282D E6A1                <1> 	OUT	INTB01,AL
  6270 0000282F FB                  <1> 	STI				; START INTERRUPTS
  6271                              <1> 	; 14/02/2015
  6272                              <1> 	;mov	di, dx
  6273                              <1> 	; 24/12/2021
  6274 00002830 89D7                <1> 	mov	edi, edx	
  6275                              <1> 	; 04/01/2015
  6276                              <1> 	;xor	di,di
  6277                              <1> drst0:
  6278 00002832 B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6279                              <1> 	;MOV	DX,HF_REG_PORT
  6280 00002834 668B15[76660000]    <1> 	MOV	DX,[HF_REG_PORT]
  6281 0000283B EE                  <1> 	OUT	DX,AL			; RESET
  6282                              <1> ;	MOV	CX,10			; DELAY COUNT
  6283                              <1> ;DRD:	DEC	CX
  6284                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6285                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6286 0000283C B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6287 00002841 E876ECFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6288                              <1>                                         ; 40 micro seconds)
  6289 00002846 A0[216C0000]        <1> 	mov	al,[CONTROL_BYTE]
  6290 0000284B 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6291 0000284D EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6292 0000284E E807040000          <1> 	CALL	NOT_BUSY
  6293 00002853 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6294 00002855 668B15[74660000]    <1> 	MOV	DX,[HF_PORT]
  6295 0000285C FEC2                <1> 	inc	dl  ; HF_PORT+1
  6296                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6297                              <1>         ;mov	cl, 10
  6298 0000285E B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6299                              <1> drst1:
  6300 00002863 EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6301 00002864 3C01                <1> 	CMP	AL,1
  6302                              <1> 	; 04/01/2015
  6303 00002866 740A                <1> 	jz	short drst2
  6304                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6305                              <1>         	; Drive/Head Register - bit 4
  6306 00002868 E2F9                <1> 	loop	drst1
  6307                              <1> DRERR:	
  6308 0000286A C605[1F6C0000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6309 00002871 C3                  <1> 	RETn
  6310                              <1> drst2:
  6311                              <1> 	; 14/02/2015
  6312                              <1> 	;mov	dx, di
  6313                              <1> 	; 24/12/2021
  6314 00002872 89FA                <1> 	mov	edx, edi
  6315                              <1> ;drst3:
  6316                              <1> ;	; 05/01/2015
  6317                              <1> ;	shl 	di,1
  6318                              <1> ;	; 04/01/2015
  6319                              <1> ;	mov	ax,[di+hd_cports]
  6320                              <1> ;	cmp	ax,[HF_REG_PORT]
  6321                              <1> ;	je	short drst4
  6322                              <1> ;	mov	[HF_REG_PORT], ax
  6323                              <1> ;	; 03/01/2015
  6324                              <1> ;	mov	ax,[di+hd_ports]
  6325                              <1> ;       mov     [HF_PORT], ax
  6326                              <1> ;	; 05/01/2014
  6327                              <1> ;	shr	di,1
  6328                              <1> ;	; 04/01/2015
  6329                              <1> ;	jmp	short drst0	; reset other controller
  6330                              <1> ;drst4:
  6331                              <1> ;	; 05/01/2015
  6332                              <1> ;	shr	di,1
  6333                              <1> ;	mov	al,[di+hd_dregs]
  6334                              <1> ;	and	al,10h ; bit 4 only
  6335                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6336                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6337                              <1> 	;
  6338 00002874 A0[78660000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6339 00002879 A801                <1> 	test	al,1
  6340                              <1> ;	jnz	short drst6
  6341 0000287B 7516                <1>         jnz     short drst4
  6342 0000287D 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6343                              <1> ;drst5:
  6344                              <1> drst3:
  6345 00002881 E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6346                              <1> 	;mov	dx,di
  6347 00002886 E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6348                              <1> 	; 04/01/2014
  6349                              <1> ;	inc	di
  6350                              <1> ;	mov	dx,di
  6351                              <1> ;	cmp	dl,[HF_NUM]
  6352                              <1> ;	jb	short drst3
  6353                              <1> ;DRE:
  6354 0000288B C605[1F6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6355 00002892 C3                  <1> 	RETn
  6356                              <1> ;drst6:
  6357                              <1> drst4:		; Drive/Head Register - bit 4
  6358 00002893 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6359                              <1>         ;jmp    short drst5
  6360 00002897 EBE8                <1>         jmp     short drst3
  6361                              <1> 
  6362                              <1> ;----------------------------------------
  6363                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6364                              <1> ;----------------------------------------
  6365                              <1> 
  6366                              <1> RETURN_STATUS:
  6367 00002899 A0[1F6C0000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6368 0000289E C605[1F6C0000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6369 000028A5 C3                  <1> 	RETn
  6370                              <1> 
  6371                              <1> ;----------------------------------------
  6372                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6373                              <1> ;----------------------------------------
  6374                              <1> 
  6375                              <1> DISK_READ:
  6376 000028A6 C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6377 000028AA E92A020000          <1>         JMP     COMMANDI
  6378                              <1> 
  6379                              <1> ;----------------------------------------
  6380                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6381                              <1> ;----------------------------------------
  6382                              <1> 
  6383                              <1> DISK_WRITE:
  6384 000028AF C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6385 000028B3 E976020000          <1>         JMP     COMMANDO
  6386                              <1> 
  6387                              <1> ;----------------------------------------
  6388                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6389                              <1> ;----------------------------------------
  6390                              <1> 
  6391                              <1> DISK_VERF:
  6392 000028B8 C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6393 000028BC E8E4020000          <1> 	CALL	COMMAND
  6394 000028C1 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6395 000028C3 E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6396 000028C8 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6397 000028CA E8E3030000          <1> 	CALL	CHECK_STATUS
  6398                              <1> VERF_EXIT:
  6399 000028CF C3                  <1> 	RETn
  6400                              <1> 
  6401                              <1> ;----------------------------------------
  6402                              <1> ;	FORMATTING	     (AH = 05H) :
  6403                              <1> ;----------------------------------------
  6404                              <1> 
  6405                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6406 000028D0 C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6407                              <1> 	;PUSH	ES
  6408                              <1> 	;PUSH	BX
  6409 000028D4 53                  <1> 	push	ebx
  6410 000028D5 E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6411                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6412 000028DA 8A430E              <1> 	mov	al, [ebx+14]
  6413 000028DD 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6414 000028E0 5B                  <1> 	pop	ebx
  6415                              <1> 	;POP	BX
  6416                              <1> 	;POP	ES
  6417 000028E1 E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6418                              <1> 
  6419                              <1> ;----------------------------------------
  6420                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6421                              <1> ;----------------------------------------
  6422                              <1> 
  6423                              <1> READ_DASD_TYPE:
  6424                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6425 000028E6 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6426                              <1> 	;PUSH	ES
  6427 000028E7 53                  <1> 	PUSH	eBX
  6428                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6429                              <1> 	;push	cs
  6430                              <1> 	;pop	ds
  6431 000028E8 66BB1000            <1>         mov	bx, KDATA
  6432 000028EC 8EDB                <1> 	mov	ds, bx
  6433                              <1> 	;mov	es, bx
  6434 000028EE C605[1F6C0000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6435 000028F5 8A1D[206C0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6436 000028FB 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6437 000028FE 38D3                <1> 	CMP	BL,DL
  6438 00002900 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6439 00002902 E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6440                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6441 00002907 8A4302              <1> 	mov	al, [ebx+2]
  6442                              <1> 	;MOV	CL,[ES:BX+14]
  6443 0000290A 8A4B0E              <1> 	mov	cl, [ebx+14]
  6444 0000290D F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6445                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6446 0000290F 668B0B              <1> 	mov	cx, [ebx]
  6447                              <1> 	;
  6448                              <1> 	; 02/01/2015 
  6449                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6450                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6451 00002912 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6452                              <1> 	;
  6453 00002914 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6454 00002917 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6455 0000291A 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6456                              <1> 	;SUB	AX,AX
  6457 0000291D 28C0                <1> 	sub	al, al
  6458 0000291F B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6459 00002921 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6460                              <1> 	;POP	ES
  6461 00002922 1F                  <1> 	POP	DS
  6462 00002923 F8                  <1> 	CLC				; CLEAR CARRY
  6463                              <1> 	;RETf	2
  6464 00002924 CA0400              <1> 	retf	4
  6465                              <1> RDT_NOT_PRESENT:
  6466                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6467                              <1> 	; 24/12/2021
  6468 00002927 29C0                <1> 	sub	eax, eax
  6469                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6470                              <1> 	;MOV	DX,AX
  6471 00002929 89C1                <1> 	mov	ecx, eax
  6472 0000292B 89C2                <1> 	mov	edx, eax
  6473 0000292D EBF2                <1> 	JMP	short RDT2
  6474                              <1> 
  6475                              <1> ;----------------------------------------
  6476                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6477                              <1> ;----------------------------------------
  6478                              <1> 
  6479                              <1> GET_PARM_N:
  6480                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6481 0000292F 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6482                              <1> 	;PUSH	ES
  6483 00002930 53                  <1> 	PUSH	eBX
  6484                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6485                              <1> 	;MOV	DS,AX
  6486                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6487                              <1> 	;JZ	short G0
  6488                              <1> 	;LES	BX,@HF1_TBL_VEC
  6489                              <1> 	;JMP	SHORT G1
  6490                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6491                              <1> ;G1:
  6492                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6493                              <1> 	; 22/12/2014
  6494                              <1> 	;push	cs
  6495                              <1> 	;pop	ds
  6496 00002931 66BB1000            <1> 	mov	bx, KDATA
  6497 00002935 8EDB                <1> 	mov	ds, bx
  6498                              <1> 	;mov	es, bx
  6499                              <1> 	;
  6500 00002937 80EA80              <1> 	SUB	DL,80H
  6501 0000293A 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6502 0000293D 7340                <1> 	JAE	short G4
  6503                              <1> 	;
  6504 0000293F 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6505                              <1> 	; 22/12/2014
  6506 00002941 88D3                <1> 	mov	bl, dl
  6507                              <1> 	;xor	bh, bh  
  6508 00002943 C0E302              <1> 	shl	bl, 2			; convert index to offset
  6509                              <1> 	;add	bx, HF_TBL_VEC
  6510 00002946 81C3[246C0000]      <1> 	add	ebx, HF_TBL_VEC
  6511                              <1> 	;mov	ax, [bx+2]
  6512                              <1> 	;mov	es, ax			; dpt segment
  6513                              <1> 	;mov	bx, [bx]		; dpt offset
  6514 0000294C 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6515                              <1> 
  6516 0000294E C605[1F6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6517                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6518 00002955 668B03              <1> 	mov	ax, [ebx]
  6519                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6520 00002958 6648                <1> 	dec	ax			; max. cylinder number
  6521 0000295A 88C5                <1> 	MOV	CH,AL
  6522 0000295C 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6523 00002960 66D1E8              <1> 	SHR	AX,1
  6524 00002963 66D1E8              <1> 	SHR	AX,1
  6525                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6526 00002966 0A430E              <1> 	or	al, [ebx+14]
  6527 00002969 88C1                <1> 	MOV	CL,AL
  6528                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6529 0000296B 8A7302              <1> 	mov	dh, [ebx+2]
  6530 0000296E FECE                <1> 	DEC	DH			; 0-N RANGE
  6531 00002970 8A15[206C0000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6532                              <1> 	;SUB	AX,AX
  6533                              <1> 	; 24/12/2021
  6534 00002976 29C0                <1> 	sub	eax, eax
  6535                              <1> 	; 27/12/2014 
  6536                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6537                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6538                              <1> 	;mov	di, bx			; HDPT offset
  6539 00002978 89DF                <1> 	mov	edi, ebx
  6540                              <1> G5:
  6541 0000297A 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6542                              <1> 	;POP	ES
  6543 0000297B 1F                  <1> 	POP	DS
  6544                              <1> 	;RETf	2
  6545 0000297C CA0400              <1> 	retf	4
  6546                              <1> G4:
  6547 0000297F C605[1F6C0000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6548                              <1> 	; 24/12/2021
  6549 00002986 29C0                <1> 	sub	eax, eax
  6550 00002988 B407                <1> 	MOV	AH,INIT_FAIL
  6551                              <1> 	;SUB	AL,AL
  6552                              <1> 	;SUB	DX,DX
  6553 0000298A 29D2                <1> 	sub	edx, edx
  6554                              <1> 	;SUB	CX,CX
  6555 0000298C 29C9                <1> 	sub	ecx, ecx
  6556 0000298E F9                  <1> 	STC				; SET ERROR FLAG
  6557 0000298F EBE9                <1> 	JMP	short G5
  6558                              <1> 
  6559                              <1> ;----------------------------------------
  6560                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6561                              <1> ;----------------------------------------
  6562                              <1> 	; 03/01/2015
  6563                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6564                              <1> 	; logical sector per logical track
  6565                              <1> 	; and logical heads - 1 would be set but
  6566                              <1> 	; it is seen as it will be good
  6567                              <1> 	; if physical parameters will be set here
  6568                              <1> 	; because, number of heads <= 16.
  6569                              <1> 	; (logical heads usually more than 16)
  6570                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6571                              <1> 	;	== INT 13h physical parameters
  6572                              <1> 
  6573                              <1> ;INIT_DRV:
  6574                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6575                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6576                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6577                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6578                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6579                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6580                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6581                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6582                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6583                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6584                              <1> ;	SUB	AX,AX
  6585                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6586                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6587                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6588                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6589                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6590                              <1> ;	CALL	CHECK_STATUS
  6591                              <1> ;INIT_EXIT:
  6592                              <1> ;	RETn
  6593                              <1> 
  6594                              <1> ; 04/01/2015
  6595                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6596                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6597                              <1> INIT_DRV:
  6598                              <1> 	;xor	ah,ah
  6599 00002991 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6600 00002993 B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6601 00002995 3825[346C0000]      <1>         cmp     [LBAMode], ah   ; 0
  6602 0000299B 7702                <1> 	ja	short idrv0
  6603 0000299D B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6604                              <1> idrv0:
  6605                              <1> 	; DL = drive number (0 based)
  6606 0000299F E8BB030000          <1> 	call	GET_VEC
  6607                              <1> 	;push	bx
  6608 000029A4 53                  <1> 	push	ebx ; 21/02/2015
  6609                              <1> 	;add	bx,ax
  6610 000029A5 01C3                <1> 	add	ebx,eax
  6611                              <1> 	;; 05/01/2015
  6612 000029A7 8A25[78660000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6613                              <1> 	;;and 	ah,1 
  6614 000029AD C0E404              <1> 	shl	ah,4
  6615 000029B0 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6616                              <1> 	;mov	al,[es:bx]
  6617 000029B3 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6618 000029B5 FEC8                <1> 	dec	al	 ; last head number 
  6619                              <1> 	;and	al,0Fh
  6620 000029B7 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6621                              <1> 	;
  6622 000029B9 C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6623 000029BD 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6624                              <1> 	;pop	bx
  6625 000029C0 5B                  <1> 	pop	ebx
  6626 000029C1 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6627 000029C3 B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6628 000029C5 803D[346C0000]00    <1> 	cmp	byte [LBAMode],0
  6629 000029CC 7702                <1> 	ja	short idrv1
  6630 000029CE B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6631                              <1> idrv1:
  6632                              <1> 	;xor	ah,ah
  6633                              <1> 	;add	bx,ax
  6634 000029D0 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6635                              <1> 	;mov	al,[es:bx]
  6636                              <1> 			; sector number
  6637 000029D2 8A03                <1> 	mov	al,[ebx]
  6638 000029D4 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6639 000029D7 28C0                <1> 	sub	al,al
  6640 000029D9 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6641 000029DC E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6642 000029E1 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6643 000029E3 E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6644 000029E8 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6645 000029EA E8C3020000          <1> 	call	CHECK_STATUS
  6646                              <1> INIT_EXIT:
  6647 000029EF C3                  <1> 	RETn
  6648                              <1> 
  6649                              <1> ;----------------------------------------
  6650                              <1> ;	READ LONG	     (AH = 0AH) :
  6651                              <1> ;----------------------------------------
  6652                              <1> 
  6653                              <1> RD_LONG:
  6654                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6655 000029F0 C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6656 000029F4 E9E0000000          <1>         JMP     COMMANDI
  6657                              <1> 
  6658                              <1> ;----------------------------------------
  6659                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6660                              <1> ;----------------------------------------
  6661                              <1> 
  6662                              <1> WR_LONG:
  6663                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6664 000029F9 C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6665 000029FD E92C010000          <1>         JMP     COMMANDO
  6666                              <1> 
  6667                              <1> ;----------------------------------------
  6668                              <1> ;	SEEK		     (AH = 0CH) :
  6669                              <1> ;----------------------------------------
  6670                              <1> 
  6671                              <1> DISK_SEEK:
  6672 00002A02 C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6673 00002A06 E89A010000          <1> 	CALL	COMMAND
  6674 00002A0B 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6675 00002A0D E80C020000          <1> 	CALL	_WAIT
  6676 00002A12 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6677 00002A14 E899020000          <1> 	CALL	CHECK_STATUS
  6678 00002A19 803D[1F6C0000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6679 00002A20 7507                <1> 	JNE	short DS_EXIT
  6680 00002A22 C605[1F6C0000]00    <1>         MOV     byte [DISK_STATUS1],0
  6681                              <1> DS_EXIT:
  6682 00002A29 C3                  <1> 	RETn
  6683                              <1> 
  6684                              <1> ;----------------------------------------
  6685                              <1> ;	TEST DISK READY      (AH = 10H) :
  6686                              <1> ;----------------------------------------
  6687                              <1> 
  6688                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6689 00002A2A E82B020000          <1> 	CALL	NOT_BUSY
  6690 00002A2F 751C                <1> 	JNZ	short TR_EX
  6691 00002A31 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6692 00002A34 668B15[74660000]    <1> 	MOV	DX,[HF_PORT]
  6693 00002A3B 80C206              <1> 	add	dl,6
  6694 00002A3E EE                  <1> 	OUT	DX,AL
  6695 00002A3F E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6696 00002A44 7507                <1> 	JNZ	short TR_EX
  6697 00002A46 C605[1F6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6698                              <1> TR_EX:	
  6699 00002A4D C3                  <1> 	RETn
  6700                              <1> 
  6701                              <1> ;----------------------------------------
  6702                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6703                              <1> ;----------------------------------------
  6704                              <1> 
  6705                              <1> HDISK_RECAL:
  6706 00002A4E C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6707 00002A52 E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6708 00002A57 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6709 00002A59 E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6710 00002A5E 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6711 00002A60 E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6712 00002A65 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6713                              <1> RECAL_X:
  6714 00002A67 E846020000          <1> 	CALL	CHECK_STATUS
  6715 00002A6C 803D[1F6C0000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6716 00002A73 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6717 00002A75 C605[1F6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6718                              <1> RECAL_EXIT:
  6719 00002A7C 803D[1F6C0000]00    <1>         CMP     byte [DISK_STATUS1],0
  6720 00002A83 C3                  <1> 	RETn
  6721                              <1> 
  6722                              <1> ;----------------------------------------
  6723                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6724                              <1> ;----------------------------------------
  6725                              <1> 
  6726                              <1> CTLR_DIAGNOSTIC:
  6727 00002A84 FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6728 00002A85 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6729                              <1> 	;AND	AL,0BFH
  6730 00002A87 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6731                              <1> 	;JMP	$+2
  6732                              <1> 	IODELAY
  2153 00002A89 EB00                <2>  jmp short $+2
  2154 00002A8B EB00                <2>  jmp short $+2
  6733 00002A8D E6A1                <1> 	OUT	INTB01,AL
  6734                              <1> 	IODELAY
  2153 00002A8F EB00                <2>  jmp short $+2
  2154 00002A91 EB00                <2>  jmp short $+2
  6735 00002A93 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6736 00002A95 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6737                              <1> 	;JMP	$+2
  6738                              <1> 	IODELAY
  2153 00002A97 EB00                <2>  jmp short $+2
  2154 00002A99 EB00                <2>  jmp short $+2
  6739 00002A9B E621                <1> 	OUT	INTA01,AL
  6740 00002A9D FB                  <1> 	STI
  6741 00002A9E E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6742 00002AA3 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6743                              <1> 	;MOV	DX, HF_PORT+7
  6744 00002AA5 668B15[74660000]    <1> 	mov	dx, [HF_PORT]
  6745 00002AAC 80C207              <1> 	add	dl, 7
  6746 00002AAF B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6747 00002AB1 EE                  <1> 	OUT	DX,AL
  6748 00002AB2 E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6749 00002AB7 B480                <1> 	MOV	AH,TIME_OUT
  6750 00002AB9 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6751                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6752 00002ABB 668B15[74660000]    <1> 	mov	dx, [HF_PORT]
  6753 00002AC2 FEC2                <1> 	inc	dl
  6754 00002AC4 EC                  <1> 	IN	AL,DX
  6755 00002AC5 A2[166C0000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6756 00002ACA B400                <1> 	MOV	AH,0
  6757 00002ACC 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6758 00002ACE 7402                <1> 	JE	SHORT CD_EXIT
  6759 00002AD0 B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6760                              <1> CD_EXIT:
  6761 00002AD2 8825[1F6C0000]      <1> 	MOV	[DISK_STATUS1],AH
  6762 00002AD8 C3                  <1> 	RETn
  6763                              <1> 
  6764                              <1> ;----------------------------------------
  6765                              <1> ; COMMANDI				:
  6766                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6767                              <1> ;	NSECTOR RETURNS ZERO		:
  6768                              <1> ;----------------------------------------
  6769                              <1> COMMANDI:
  6770 00002AD9 E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6771 00002ADE 724D                <1> 	JC	short CMD_ABORT
  6772                              <1> 	;MOV	DI,BX
  6773 00002AE0 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6774 00002AE2 E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6775 00002AE7 7544                <1> 	JNZ	short CMD_ABORT
  6776                              <1> CMD_I1:
  6777 00002AE9 E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6778 00002AEE 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6779                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6780 00002AF0 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6781                              <1> 	;MOV	DX,HF_PORT
  6782 00002AF5 668B15[74660000]    <1> 	mov	dx,[HF_PORT]
  6783 00002AFC FA                  <1> 	CLI
  6784 00002AFD FC                  <1> 	CLD
  6785 00002AFE F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6786 00002B01 FB                  <1> 	STI
  6787 00002B02 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6788 00002B06 7419                <1> 	JZ	CMD_I3
  6789 00002B08 E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6790 00002B0D 721E                <1> 	JC	short TM_OUT
  6791                              <1> 	;MOV	DX,HF_PORT
  6792 00002B0F 668B15[74660000]    <1> 	mov	dx,[HF_PORT]
  6793                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6794 00002B16 B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6795 00002B1B EC                  <1> CMD_I2: IN	AL,DX
  6796                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6797 00002B1C 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6798 00002B1E 47                  <1> 	INC	eDI
  6799 00002B1F E2FA                <1> 	LOOP	CMD_I2
  6800 00002B21 E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6801 00002B26 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6802 00002B28 FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6803 00002B2B 75BC                <1> 	JNZ	SHORT CMD_I1
  6804                              <1> CMD_ABORT:
  6805 00002B2D C3                  <1> TM_OUT: RETn
  6806                              <1> 
  6807                              <1> ;----------------------------------------
  6808                              <1> ; COMMANDO				:
  6809                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6810                              <1> ;	NSECTOR RETURNS ZERO		:
  6811                              <1> ;----------------------------------------
  6812                              <1> COMMANDO:
  6813 00002B2E E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6814 00002B33 72F8                <1> 	JC	short CMD_ABORT
  6815 00002B35 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6816 00002B37 E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6817 00002B3C 75EF                <1> 	JNZ	short CMD_ABORT
  6818 00002B3E E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6819 00002B43 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6820                              <1> CMD_O1: ;PUSH	DS
  6821                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6822                              <1> 	;POP	DS
  6823                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6824                              <1> 	;MOV	DX,HF_PORT
  6825                              <1> 	; 01/02/2015
  6826 00002B45 668B15[74660000]    <1> 	mov	dx, [HF_PORT]
  6827                              <1> 	;push	es
  6828                              <1> 	;pop	ds
  6829                              <1> 	;mov	cx, 256
  6830 00002B4C B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6831 00002B51 FA                  <1> 	CLI
  6832 00002B52 FC                  <1> 	CLD
  6833 00002B53 F3666F              <1> 	REP	OUTSW
  6834 00002B56 FB                  <1> 	STI
  6835                              <1> 	;POP	DS			; RESTORE DS
  6836 00002B57 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6837 00002B5B 7419                <1> 	JZ	short CMD_O3
  6838 00002B5D E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6839 00002B62 72C9                <1> 	JC	short TM_OUT
  6840                              <1> 	;MOV	DX,HF_PORT
  6841 00002B64 668B15[74660000]    <1> 	mov	dx, [HF_PORT]
  6842                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6843 00002B6B B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6844                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6845 00002B70 8A06                <1> 	mov	al, [esi]
  6846 00002B72 EE                  <1> 	OUT	DX,AL
  6847 00002B73 46                  <1> 	INC	eSI
  6848 00002B74 E2FA                <1> 	LOOP	CMD_O2
  6849                              <1> CMD_O3:
  6850 00002B76 E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6851 00002B7B 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6852 00002B7D E830010000          <1> 	CALL	CHECK_STATUS
  6853 00002B82 75A9                <1> 	JNZ	short CMD_ABORT
  6854 00002B84 F605[156C0000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6855 00002B8B 75B8                <1> 	JNZ	SHORT CMD_O1
  6856                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6857 00002B8D 668B15[74660000]    <1> 	mov	dx, [HF_PORT]
  6858                              <1> 	;add	dl, 2
  6859 00002B94 FEC2                <1> 	inc	dl
  6860 00002B96 FEC2                <1> 	inc	dl
  6861 00002B98 EC                  <1> 	IN	AL,DX			;
  6862 00002B99 A8FF                <1> 	TEST	AL,0FFH 		;
  6863 00002B9B 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6864 00002B9D C605[1F6C0000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6865                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6866                              <1> CMD_O4:
  6867 00002BA4 C3                  <1> 	RETn
  6868                              <1> 
  6869                              <1> ;--------------------------------------------------------
  6870                              <1> ; COMMAND						:
  6871                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6872                              <1> ; OUTPUT						:
  6873                              <1> ;	BL = STATUS					:
  6874                              <1> ;	BH = ERROR REGISTER				:
  6875                              <1> ;--------------------------------------------------------
  6876                              <1> 
  6877                              <1> COMMAND:
  6878 00002BA5 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6879                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6880                              <1> COMMAND1:
  6881                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6882 00002BA6 E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6883                              <1> 	;;POP	CX
  6884 00002BAB 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6885 00002BAD 803D[1F6C0000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6886                              <1> 	;JZ	short CMD_TIMEOUT
  6887                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6888                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6889 00002BB4 7507                <1> 	jne	short COMMAND4
  6890                              <1> CMD_TIMEOUT:
  6891 00002BB6 C605[1F6C0000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6892                              <1> COMMAND4:
  6893 00002BBD 5B                  <1> 	POP	eBX
  6894 00002BBE 803D[1F6C0000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6895 00002BC5 C3                  <1> 	RETn
  6896                              <1> COMMAND2:
  6897 00002BC6 5B                  <1> 	POP	eBX
  6898 00002BC7 57                  <1> 	PUSH	eDI
  6899 00002BC8 C605[176C0000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6900 00002BCF FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6901 00002BD0 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6902                              <1> 	;AND	AL,0BFH
  6903 00002BD2 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6904                              <1> 	;JMP	$+2
  6905                              <1> 	IODELAY
  2153 00002BD4 EB00                <2>  jmp short $+2
  2154 00002BD6 EB00                <2>  jmp short $+2
  6906 00002BD8 E6A1                <1> 	OUT	INTB01,AL
  6907 00002BDA E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6908 00002BDC 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6909                              <1> 	;JMP	$+2
  6910                              <1> 	IODELAY
  2153 00002BDE EB00                <2>  jmp short $+2
  2154 00002BE0 EB00                <2>  jmp short $+2
  6911 00002BE2 E621                <1> 	OUT	INTA01,AL
  6912 00002BE4 FB                  <1> 	STI
  6913 00002BE5 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6914                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6915 00002BE7 668B15[74660000]    <1> 	mov	dx, [HF_PORT]
  6916 00002BEE FEC2                <1> 	inc	dl
  6917 00002BF0 F605[216C0000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6918 00002BF7 7411                <1> 	JZ	short COMMAND3
  6919 00002BF9 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6920 00002BFC 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6921 00002BFE 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6922 00002C00 7208                <1> 	JB	short COMMAND3
  6923 00002C02 3C40                <1> 	CMP	AL,40H
  6924 00002C04 7704                <1> 	JA	short COMMAND3
  6925 00002C06 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6926                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6927                              <1> COMMAND3:
  6928 00002C0A 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6929 00002C0E EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6930                              <1> 	IODELAY
  2153 00002C0F EB00                <2>  jmp short $+2
  2154 00002C11 EB00                <2>  jmp short $+2
  6931 00002C13 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6932 00002C14 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6933 00002C16 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6934 00002C1A 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6935 00002C1C 5F                  <1> 	POP	eDI
  6936 00002C1D C3                  <1> 	RETn				; ZERO FLAG IS SET
  6937                              <1> 
  6938                              <1> ;CMD_TIMEOUT:
  6939                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6940                              <1> ;COMMAND4:
  6941                              <1> ;	POP	BX
  6942                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6943                              <1> ;	RETn
  6944                              <1> 
  6945                              <1> ;----------------------------------------
  6946                              <1> ;	WAIT FOR INTERRUPT		:
  6947                              <1> ;----------------------------------------
  6948                              <1> ;WAIT:
  6949                              <1> _WAIT:
  6950 00002C1E FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6951                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6952                              <1> 	;CLC
  6953                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6954                              <1> 	;INT	15H
  6955                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6956                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6957                              <1> 
  6958                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6959                              <1> 	;; 21/02/2015
  6960                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6961                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6962 00002C1F B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6963                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6964                              <1> ;-----	WAIT LOOP
  6965                              <1> 
  6966                              <1> WT1:	
  6967                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6968 00002C24 F605[176C0000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6969                              <1> 	;LOOPZ	WT1
  6970 00002C2B 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6971                              <1> 	;DEC	BL
  6972                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6973                              <1> 
  6974                              <1> WT1_hi:
  6975 00002C2D E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6976 00002C2F A810                <1> 	test	al, 10h			; transition on memory
  6977 00002C31 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6978                              <1> WT1_lo:
  6979 00002C33 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6980 00002C35 A810                <1> 	test	al, 10h			
  6981 00002C37 74FA                <1> 	jz	short WT1_lo
  6982 00002C39 E2E9                <1> 	loop	WT1
  6983                              <1> 	;;or	bl, bl
  6984                              <1> 	;;jz	short WT2	
  6985                              <1> 	;;dec	bl
  6986                              <1> 	;;jmp	short WT1
  6987                              <1> 	;dec	bl
  6988                              <1> 	;jnz	short WT1	
  6989                              <1> 
  6990 00002C3B C605[1F6C0000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6991 00002C42 EB0E                <1> 	JMP	SHORT WT4
  6992 00002C44 C605[1F6C0000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6993 00002C4B C605[176C0000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6994 00002C52 803D[1F6C0000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6995 00002C59 C3                  <1> 	RETn
  6996                              <1> 
  6997                              <1> ;----------------------------------------
  6998                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  6999                              <1> ;----------------------------------------
  7000                              <1> NOT_BUSY:
  7001 00002C5A FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  7002                              <1> 	;PUSH	eBX
  7003                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  7004 00002C5B 668B15[74660000]    <1> 	mov	DX, [HF_PORT]
  7005 00002C62 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  7006                              <1> 	;MOV	BL,DELAY_1
  7007                              <1> 					; wait for 10 seconds
  7008                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  7009                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  7010                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  7011 00002C65 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  7012                              <1> 	;
  7013                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  7014                              <1> NB1:	
  7015 00002C6A EC                  <1> 	IN	AL,DX			; CHECK STATUS
  7016                              <1> 	;TEST	AL,ST_BUSY
  7017 00002C6B 2480                <1> 	and	al, ST_BUSY
  7018                              <1> 	;LOOPNZ	NB1
  7019 00002C6D 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  7020                              <1> 	;DEC	BL			
  7021                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  7022                              <1> 
  7023 00002C6F E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  7024 00002C71 A810                <1> 	TEST	AL,010H			; transition on memory
  7025 00002C73 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  7026 00002C75 E461                <1> NB1_lo: IN	AL,SYS1
  7027 00002C77 A810                <1> 	TEST	AL,010H
  7028 00002C79 74FA                <1> 	JZ	short NB1_lo
  7029 00002C7B E2ED                <1> 	LOOP	NB1
  7030                              <1> 	;dec	bl
  7031                              <1> 	;jnz	short NB1
  7032                              <1> 	;
  7033                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  7034                              <1> ;;	jb	short NB1
  7035                              <1> 	;
  7036                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  7037                              <1> 	;JMP	SHORT NB3
  7038 00002C7D B080                <1> 	mov	al, TIME_OUT
  7039                              <1> NB2:	
  7040                              <1> 	;MOV	byte [DISK_STATUS1],0
  7041                              <1> ;NB3:	
  7042                              <1> 	;POP	eBX
  7043 00002C7F A2[1F6C0000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  7044                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  7045 00002C84 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  7046 00002C86 C3                  <1> 	RETn
  7047                              <1> 
  7048                              <1> ;----------------------------------------
  7049                              <1> ;	WAIT FOR DATA REQUEST		:
  7050                              <1> ;----------------------------------------
  7051                              <1> WAIT_DRQ:
  7052                              <1> 	;MOV	CX,DELAY_3
  7053                              <1> 	;MOV	DX,HF_PORT+7
  7054 00002C87 668B15[74660000]    <1> 	mov	dx, [HF_PORT]
  7055 00002C8E 80C207              <1> 	add	dl, 7
  7056                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  7057                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  7058                              <1> 					; (but it is written as 2000
  7059                              <1> 					; micro seconds in ATORGS.ASM file
  7060                              <1> 					; of Award Bios - 1999, D1A0622)
  7061 00002C91 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  7062 00002C96 EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  7063 00002C97 A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  7064 00002C99 7516                <1> 	JNZ	short WQ_OK
  7065                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  7066                              <1> WQ_hi:	
  7067 00002C9B E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  7068 00002C9D A810                <1> 	TEST	AL,010H			; transition on memory
  7069 00002C9F 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  7070 00002CA1 E461                <1> WQ_lo:  IN      AL,SYS1
  7071 00002CA3 A810                <1> 	TEST	AL,010H
  7072 00002CA5 74FA                <1> 	JZ	SHORT WQ_lo
  7073 00002CA7 E2ED                <1> 	LOOP	WQ_1
  7074                              <1> 
  7075 00002CA9 C605[1F6C0000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  7076 00002CB0 F9                  <1> 	STC
  7077                              <1> WQ_OK:
  7078 00002CB1 C3                  <1> 	RETn
  7079                              <1> ;WQ_OK:	;CLC
  7080                              <1> ;	RETn
  7081                              <1> 
  7082                              <1> ;----------------------------------------
  7083                              <1> ;	CHECK FIXED DISK STATUS 	:
  7084                              <1> ;----------------------------------------
  7085                              <1> CHECK_STATUS:
  7086 00002CB2 E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  7087 00002CB7 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  7088 00002CB9 A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  7089 00002CBB 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  7090 00002CBD E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  7091                              <1> CHECK_S1:
  7092 00002CC2 803D[1F6C0000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  7093 00002CC9 C3                  <1> 	RETn
  7094                              <1> 
  7095                              <1> ;----------------------------------------
  7096                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  7097                              <1> ;----------------------------------------
  7098                              <1> CHECK_ST:
  7099                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  7100 00002CCA 668B15[74660000]    <1> 	mov	dx, [HF_PORT]
  7101 00002CD1 80C207              <1> 	add	dl, 7
  7102 00002CD4 EC                  <1> 	IN	AL,DX
  7103 00002CD5 A2[156C0000]        <1> 	MOV	[HF_STATUS],AL
  7104 00002CDA B400                <1> 	MOV	AH,0
  7105 00002CDC A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  7106 00002CDE 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  7107 00002CE0 B4CC                <1> 	MOV	AH,WRITE_FAULT
  7108 00002CE2 A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7109 00002CE4 7514                <1> 	JNZ	short CKST_EXIT
  7110 00002CE6 B4AA                <1> 	MOV	AH,NOT_RDY
  7111 00002CE8 A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7112 00002CEA 740E                <1> 	JZ	short CKST_EXIT
  7113 00002CEC B440                <1> 	MOV	AH,BAD_SEEK
  7114 00002CEE A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7115 00002CF0 7408                <1> 	JZ	short CKST_EXIT
  7116 00002CF2 B411                <1> 	MOV	AH,DATA_CORRECTED
  7117 00002CF4 A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7118 00002CF6 7502                <1> 	JNZ	short CKST_EXIT
  7119 00002CF8 B400                <1> 	MOV	AH,0
  7120                              <1> CKST_EXIT:
  7121 00002CFA 8825[1F6C0000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7122 00002D00 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7123 00002D03 7403                <1> 	JZ	short CKST_EX1
  7124 00002D05 80FC00              <1> 	CMP	AH,0
  7125                              <1> CKST_EX1:
  7126 00002D08 C3                  <1> 	RETn
  7127                              <1> 
  7128                              <1> ;----------------------------------------
  7129                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7130                              <1> ;----------------------------------------
  7131                              <1> CHECK_ER:
  7132                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7133 00002D09 668B15[74660000]    <1> 	mov	dx, [HF_PORT]		;
  7134 00002D10 FEC2                <1> 	inc	dl
  7135 00002D12 EC                  <1> 	IN	AL,DX
  7136 00002D13 A2[166C0000]        <1> 	MOV	[HF_ERROR],AL
  7137 00002D18 53                  <1> 	PUSH	eBX ; 21/02/2015
  7138 00002D19 B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7139 00002D1E D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7140 00002D20 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7141 00002D22 E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7142 00002D24 BB[68660000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7143 00002D29 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7144                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7145                              <1> 	;mov	ah, [bx]
  7146 00002D2B 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7147 00002D2D 8825[1F6C0000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7148 00002D33 5B                  <1> 	POP	eBX
  7149 00002D34 80FC00              <1> 	CMP	AH,0
  7150 00002D37 C3                  <1> 	RETn
  7151                              <1> 
  7152                              <1> ;--------------------------------------------------------
  7153                              <1> ; CHECK_DMA						:
  7154                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7155                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7156                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7157                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7158                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7159                              <1> ;  -ERROR OTHERWISE					:
  7160                              <1> ;--------------------------------------------------------
  7161                              <1> CHECK_DMA:
  7162                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7163                              <1> 	; 24/12/2021
  7164 00002D38 50                  <1> 	push	eax
  7165 00002D39 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7166 00002D3D F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7167 00002D41 7404                <1> 	JZ	short CKD1
  7168 00002D43 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7169 00002D47 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7170 00002D4A 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7171 00002D4C 7207                <1> 	JB	short CKDERR		; TOO MANY
  7172 00002D4E 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7173 00002D50 7203                <1> 	JB	short CKDERR		; ERROR
  7174 00002D52 F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7175                              <1> 	;POP	AX
  7176                              <1> 	; 24/12/2021
  7177 00002D53 58                  <1> 	pop	eax
  7178 00002D54 C3                  <1> 	RETn				; NORMAL RETURN
  7179 00002D55 F9                  <1> CKDERR: STC				; INDICATE ERROR
  7180 00002D56 C605[1F6C0000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7181                              <1> 	;POP	AX
  7182                              <1> 	; 24/12/2021
  7183 00002D5D 58                  <1> 	pop	eax	
  7184 00002D5E C3                  <1> 	RETn
  7185                              <1> 
  7186                              <1> ;----------------------------------------
  7187                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7188                              <1> ;----------------------------------------
  7189                              <1> 					
  7190                              <1> ; INPUT -> DL = 0 based drive number
  7191                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7192                              <1> 
  7193                              <1> GET_VEC:
  7194                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7195                              <1> 	;MOV	ES,AX
  7196                              <1> 	;TEST	DL,1
  7197                              <1> 	;JZ	short GV_0
  7198                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7199                              <1> ;	JMP	SHORT GV_EXIT
  7200                              <1> ;GV_0:
  7201                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7202                              <1> ;
  7203                              <1> 	;xor	bh, bh
  7204 00002D5F 31DB                <1> 	xor	ebx, ebx
  7205 00002D61 88D3                <1> 	mov	bl, dl
  7206                              <1> 	;;02/01/2015
  7207                              <1> 	;;shl	bl, 1			; port address offset
  7208                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7209                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7210 00002D63 C0E302              <1> 	shl	bl, 2	;;
  7211                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7212 00002D66 81C3[246C0000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7213                              <1> 	;push	word [bx+2]		; dpt segment
  7214                              <1> 	;pop	es
  7215                              <1> 	;mov	bx, [bx]		; dpt offset
  7216 00002D6C 8B1B                <1> 	mov	ebx, [ebx]		
  7217                              <1> ;GV_EXIT:
  7218 00002D6E C3                  <1> 	RETn
  7219                              <1> 
  7220                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7221                              <1> hdc1_int: ; 21/02/2015
  7222                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7223                              <1> ;								:
  7224                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7225                              <1> ;								:
  7226                              <1> ;----------------------------------------------------------------
  7227                              <1> 
  7228                              <1> ; 22/12/2014
  7229                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7230                              <1> ;	 '11/15/85'
  7231                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7232                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7233                              <1> 
  7234                              <1> ;int_76h:
  7235                              <1> HD_INT:
  7236                              <1> 	;push	ax
  7237                              <1> 	; 24/12/2021
  7238 00002D6F 50                  <1> 	push	eax
  7239 00002D70 1E                  <1> 	push	ds
  7240                              <1> 	;CALL	DDS
  7241                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7242 00002D71 66B81000            <1> 	mov	ax, KDATA
  7243 00002D75 8ED8                <1> 	mov 	ds, ax
  7244                              <1> 	;
  7245                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7246                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7247 00002D77 C605[176C0000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7248                              <1> 	;
  7249                              <1> 	;push	dx
  7250                              <1> 	; 24/12/2021
  7251 00002D7E 52                  <1> 	push	edx
  7252 00002D7F 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7253                              <1> 					; Clear Controller
  7254                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7255 00002D83 EC                  <1> 	in	al, dx			;
  7256                              <1> 	;pop	dx
  7257                              <1> 	; 24/12/2021
  7258 00002D84 5A                  <1> 	pop	edx
  7259                              <1> 	NEWIODELAY
  2158 00002D85 E6EB                <2>  out 0EBh,al
  7260                              <1> 	;
  7261 00002D87 B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7262 00002D89 E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7263                              <1> 	;JMP	$+2			; WAIT
  7264                              <1> 	NEWIODELAY
  2158 00002D8B E6EB                <2>  out 0EBh,al
  7265 00002D8D E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7266 00002D8F 1F                  <1> 	pop	ds
  7267                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7268                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7269                              <1> 	;INT	15H			;  INTERRUPT
  7270                              <1> irq15_iret: ; 25/02/2015
  7271                              <1> 	;pop	ax
  7272                              <1> 	; 24/12/2021
  7273 00002D90 58                  <1> 	pop	eax
  7274 00002D91 CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7275                              <1> 
  7276                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7277                              <1> hdc2_int: ; 21/02/2015
  7278                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7279                              <1> ;								:
  7280                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7281                              <1> ;								:
  7282                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7283                              <1> 
  7284                              <1> ;int_77h:
  7285                              <1> HD1_INT:
  7286                              <1> 	;push	ax
  7287                              <1> 	; 24/12/2021
  7288 00002D92 50                  <1> 	push	eax
  7289                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7290                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7291 00002D93 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7292 00002D95 E6A0                <1> 	out	0A0h, al
  7293 00002D97 EB00                <1>         jmp short $+2
  7294 00002D99 EB00                <1> 	jmp short $+2
  7295 00002D9B E4A0                <1> 	in	al, 0A0h
  7296 00002D9D 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7297 00002D9F 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7298                              <1> 	;
  7299 00002DA1 1E                  <1> 	push	ds
  7300                              <1> 	;CALL	DDS
  7301                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7302 00002DA2 66B81000            <1> 	mov	ax, KDATA
  7303 00002DA6 8ED8                <1> 	mov 	ds, ax
  7304                              <1> 	;
  7305                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7306                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7307 00002DA8 800D[176C0000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7308                              <1> 	;
  7309                              <1> 	;push	dx
  7310                              <1> 	; 24/12/2021
  7311 00002DAF 52                  <1> 	push	edx
  7312 00002DB0 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7313                              <1> 					; Clear Controller (Award BIOS 1999)
  7314 00002DB4 EBCD                <1> 	jmp	short Clear_IRQ1415
  7315                              <1> 
  7316                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7317                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7318                              <1> 
  7319                              <1> ;////////////////////////////////////////////////////////////////////
  7320                              <1> ;; END OF DISK I/O SYTEM ///
  2097                                  %include 'memory.inc'  ; 09/03/2015
  2098                              <1> ; MEMORY.ASM - Retro UNIX 386 v1.1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2099                              <1> ; Retro UNIX 386 v1.1 Kernel (unix386.s, v0.2.1.1) - MEMORY.INC
  2100                              <1> ; Last Modification: 31/12/2021
  2101                              <1> ;
  2102                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2103                              <1> 
  2104                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2105                              <1> 
  2106                              <1> ;;04/11/2014 (unix386.s)	
  2107                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2108                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2109                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2110                              <1> ;;
  2111                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2112                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2113                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2114                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2115                              <1> 
  2116                              <1> ; 27/04/2015
  2117                              <1> ; 09/03/2015
  2118                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2119                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2120                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2121                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2122                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2123                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2124                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2125                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2126                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2127                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2128                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2129                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2130                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2131                              <1> SWP_DISK_READ_ERR 	   equ 40
  2132                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2133                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2134                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2135                              <1> SWP_DISK_WRITE_ERR         equ 44
  2136                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2137                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2138                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2139                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2140                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2141                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2142                              <1> 					; (Indicates that the page is not allocated
  2143                              <1> 					; for the process, it is a shared or system
  2144                              <1>                                         ; page, it must not be deallocated!)
  2145                              <1> ; 14/12/2020
  2146                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2147                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2148                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2149                              <1> 				; (Out of memory allocation table)	
  2150                              <1> ;
  2151                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2152                              <1> ;;
  2153                              <1> ;; 10/10/2014
  2154                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2155                              <1> ;;
  2156                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2157                              <1> ;;	(virtual address = physical address)
  2158                              <1> ;; KERNEL PAGE TABLES:
  2159                              <1> ;;	Kernel page directory and all page tables are
  2160                              <1> ;;	on memory as initialized, as equal to physical memory
  2161                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2162                              <1> ;;
  2163                              <1> ;;	what for: User pages may be swapped out, when accessing
  2164                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2165                              <1> ;;	kernel would have to swap it in! But it is also may be
  2166                              <1> ;;	in use by a user process. (In system/kernel mode
  2167                              <1> ;;	kernel can access all memory pages even if they are
  2168                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2169                              <1> ;;	cause conflicts.) 
  2170                              <1> ;;	
  2171                              <1> ;;	As result of these conditions,
  2172                              <1> ;;	all kernel pages must be initialized as equal to 
  2173                              <1> ;;	physical layout for preventing page faults. 
  2174                              <1> ;;	Also, calling "allocate page" procedure after
  2175                              <1> ;;	a page fault can cause another page fault (double fault)
  2176                              <1> ;;	if all kernel page tables would not be initialized.
  2177                              <1> ;;
  2178                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2179                              <1> ;;	memory allocation table. (double word aligned)
  2180                              <1> ;;
  2181                              <1> ;;	[next_page] = first/next free space to be searched
  2182                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2183                              <1> ;;
  2184                              <1> ;;	[last_page] = End of memory (users space), as offset
  2185                              <1> ;;	to memory allocation table. (double word aligned)
  2186                              <1> ;;
  2187                              <1> ;; USER PAGE TABLES:
  2188                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2189                              <1> ;;		'ready only' marked copies of the 
  2190                              <1> ;;		parent process's page table entries (for
  2191                              <1> ;;		same physical memory).
  2192                              <1> ;;		(A page will be copied to a new page after
  2193                              <1> ;;		 if it causes R/W page fault.)
  2194                              <1> ;;
  2195                              <1> ;;	Every user process has own (different)
  2196                              <1> ;;	page directory and page tables.	
  2197                              <1> ;;
  2198                              <1> ;;	Code starts at virtual address 0, always.
  2199                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2200                              <1> ;;	(Programs can be written/developed as simple
  2201                              <1> ;;	 flat memory programs.)
  2202                              <1> ;;
  2203                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2204                              <1> ;;	Memory page will be allocated by kernel only 
  2205                              <1> ;;		(in kernel/system mode only).
  2206                              <1> ;;	* After a
  2207                              <1> ;;	  - 'not present' page fault
  2208                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2209                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2210                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2211                              <1> ;;	  request by running process.
  2212                              <1> ;;	* While creating a process, allocating a new buffer,
  2213                              <1> ;;	  new page tables etc.
  2214                              <1> ;;
  2215                              <1> ;;	At first,
  2216                              <1> ;;	- 'allocate page' procedure will be called;
  2217                              <1> ;,	   if it will return with a valid (>0) physical address
  2218                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2219                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2220                              <1> ;;	- 'allocate page' will be called for allocating page
  2221                              <1> ;;	   directory, page table and running space (data/code).
  2222                              <1> ;;	- every successful 'allocate page' call will decrease
  2223                              <1> ;;	  'free_pages' count (pointer).
  2224                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2225                              <1> ;;	  if 'free_pages' points to a ZERO.
  2226                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2227                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2228                              <1> ;;	  error except errors caused by attribute conflicts.
  2229                              <1> ;;	 (swapper functions)	 
  2230                              <1> ;;					
  2231                              <1> ;;	At second,
  2232                              <1> ;;	- page directory entry will be updated then page table
  2233                              <1> ;;	  entry will be updated.		
  2234                              <1> ;;
  2235                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2236                              <1> ;;	- M.A.T. has a size according to available memory as
  2237                              <1> ;;	  follows:
  2238                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2239                              <1> ;;		  - a bit with value of 0 means allocated page
  2240                              <1> ;;		  - a bit with value of 1 means a free page
  2241                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2242                              <1> ;;	  depending on M.A.T.
  2243                              <1> ;;		(NOTE: Free page count will not be checked
  2244                              <1> ;;		again -on M.A.T.- after initialization. 
  2245                              <1> ;;		Kernel will trust on initial count.)
  2246                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2247                              <1> ;;	  and it will be increased by deallocation procedures.
  2248                              <1> ;;	
  2249                              <1> ;;	- Available memory will be calculated during
  2250                              <1> ;;	  the kernel's initialization stage (in real mode).
  2251                              <1> ;;	  Memory allocation table and kernel page tables 
  2252                              <1> ;;	  will be formatted/sized as result of available
  2253                              <1> ;;	  memory calculation before paging is enabled.
  2254                              <1> ;;
  2255                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2256                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2257                              <1> ;;	- Memory allocation for kernel page directory size 
  2258                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2259                              <1> ;;	  for page tables)
  2260                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2261                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2262                              <1> ;;	- User (available) space will be started 
  2263                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2264                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2265                              <1> ;;	  memory allocation table and kernel's page directory
  2266                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2267                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2268                              <1> ;; 	  for buffers.
  2269                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2270                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2271                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2272                              <1> ;;
  2273                              <1> ;; For 1GB Available Memory:
  2274                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2275                              <1> ;;	- Memory allocation for kernel page directory size 
  2276                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2277                              <1> ;;	  for page tables)
  2278                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2279                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2280                              <1> ;;	- User (available) space will be started 
  2281                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2282                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2283                              <1> ;;	  memory allocation table and kernel's page directory
  2284                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2285                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2286                              <1> ;; 	  for buffers.
  2287                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2288                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2289                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2290                              <1> ;;
  2291                              <1> ;;
  2292                              <1> 
  2293                              <1> ;;************************************************************************************
  2294                              <1> ;; 
  2295                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2296                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2297                              <1> 
  2298                              <1> ;; Main factor: "sys fork" system call 
  2299                              <1> ;;	
  2300                              <1> ;; 		FORK
  2301                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2302                              <1> ;;  writable pages ---->|
  2303                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2304                              <1> ;; 
  2305                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2306                              <1> ;; 
  2307                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2308                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2309                              <1> ;;       -while R/W bit is 0-. 
  2310                              <1> ;; 
  2311                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2312                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2313                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2314                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2315                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2316                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2317                              <1> ;; 
  2318                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2319                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2320                              <1> ;;   Parent's PTE attributes are not changed.
  2321                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2322                              <1> ;;    destroy/mix previous fork result).
  2323                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2324                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2325                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2326                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2327                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2328                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2329                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2330                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2331                              <1> ;; 
  2332                              <1> ;; !? WHAT FOR (duplication after duplication):
  2333                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2334                              <1> ;; program/executable code continues from specified location as child process, 
  2335                              <1> ;; returns back previous code location as parent process, every child after 
  2336                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2337                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2338                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2339                              <1> ;; was copied to child's process segment (all of code and data) according to
  2340                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2341                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2342                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2343                              <1> ;; (complete running image of parent process) to the child process; 
  2344                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2345                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2346                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2347                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2348                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2349                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2350                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2351                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2352                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2353                              <1> ;; for sharing same read only pages between parent and child processes.
  2354                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2355                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2356                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2357                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2358                              <1> ;; -deallocation problem-.
  2359                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2360                              <1> ;; 
  2361                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2362                              <1> ;; # Page fault handler will do those:
  2363                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2364                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2365                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2366                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2367                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2368                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2369                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2370                              <1> ;;     to child process.)	
  2371                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2372                              <1> ;; # Page fault handler will do those:
  2373                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2374                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2375                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2376                              <1> ;;     address or not. 
  2377                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2378                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2379                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2380                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2381                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2382                              <1> ;; 
  2383                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2384                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2385                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2386                              <1> ;;       duplication method details, it is not possible multiple child processes
  2387                              <1> ;;       were using same page with duplicated PTEs.
  2388                              <1> ;; 
  2389                              <1> ;;************************************************************************************   
  2390                              <1> 
  2391                              <1> ;; 08/10/2014
  2392                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2393                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2394                              <1> 
  2395                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2396                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2397                              <1> ;; (25/08/2014, Revision: 5057) file 
  2398                              <1> ;; by KolibriOS Team (2004-2012)
  2399                              <1> 
  2400                              <1> allocate_page:
  2401                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2402                              <1> 	; 01/07/2015
  2403                              <1> 	; 05/05/2015
  2404                              <1> 	; 30/04/2015
  2405                              <1> 	; 16/10/2014
  2406                              <1> 	; 08/10/2014
  2407                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2408                              <1> 	;
  2409                              <1> 	; INPUT -> none
  2410                              <1> 	;
  2411                              <1> 	; OUTPUT ->
  2412                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2413                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2414                              <1> 	;
  2415                              <1> 	;	CF = 1 and EAX = 0 
  2416                              <1> 	; 		   if there is not a free page to be allocated	
  2417                              <1> 	;
  2418                              <1> 	; Modified Registers -> none (except EAX)
  2419                              <1> 	;
  2420 00002DB6 A1[906B0000]        <1> 	mov	eax, [free_pages]
  2421 00002DBB 21C0                <1> 	and	eax, eax
  2422 00002DBD 7438                <1> 	jz	short out_of_memory
  2423                              <1> 	;
  2424 00002DBF 53                  <1> 	push	ebx
  2425 00002DC0 51                  <1> 	push	ecx
  2426                              <1> 	;
  2427 00002DC1 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2428 00002DC6 89D9                <1> 	mov	ecx, ebx
  2429                              <1>  				     ; NOTE: 32 (first_page) is initial
  2430                              <1> 				     ; value of [next_page].
  2431                              <1> 				     ; It points to the first available
  2432                              <1> 				     ; page block for users (ring 3) ...	
  2433                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2434                              <1> 				     ; (at the of the first 4 MB)		
  2435 00002DC8 031D[946B0000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2436                              <1> 				 ; next_free_page >> 5
  2437 00002DCE 030D[986B0000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2438                              <1> 				 ; (total_pages - 1) >> 5
  2439                              <1> al_p_scan:
  2440 00002DD4 39CB                <1> 	cmp	ebx, ecx
  2441 00002DD6 770A                <1> 	ja	short al_p_notfound
  2442                              <1> 	;
  2443                              <1> 	; 01/07/2015
  2444                              <1> 	; AMD64 Architecture Programmers Manual
  2445                              <1> 	; Volume 3:
  2446                              <1> 	; General-Purpose and System Instructions
  2447                              <1> 	;
  2448                              <1> 	; BSF - Bit Scan Forward
  2449                              <1> 	;
  2450                              <1> 	;   Searches the value in a register or a memory location
  2451                              <1> 	;   (second operand) for the least-significant set bit. 
  2452                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2453                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2454                              <1> 	;   register (first operand). If the second operand contains 0, 
  2455                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2456                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2457                              <1> 	;   of the searched value
  2458                              <1> 	;
  2459 00002DD8 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2460                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2461                              <1> 			   ; loads the destination with an index to
  2462                              <1> 			   ; first set bit. (0 -> 31) 
  2463                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2464 00002DDB 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2465                              <1> 			 ;
  2466                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2467                              <1> 			 ;	  with value of 1 means 
  2468                              <1> 			 ;	  the corresponding page is free 
  2469                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2470 00002DDD 83C304              <1> 	add	ebx, 4
  2471                              <1> 			 ; We return back for searching next page block
  2472                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2473                              <1> 			 ;	 we always will find at least 1 free page here.
  2474 00002DE0 EBF2                <1>         jmp     short al_p_scan
  2475                              <1> 	;
  2476                              <1> al_p_notfound:
  2477 00002DE2 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2478 00002DE8 890D[946B0000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2479                              <1> 				 ; (deallocate_page procedure will change it)
  2480 00002DEE 31C0                <1> 	xor	eax, eax
  2481 00002DF0 A3[906B0000]        <1> 	mov	[free_pages], eax ; 0
  2482 00002DF5 59                  <1> 	pop	ecx
  2483 00002DF6 5B                  <1> 	pop	ebx
  2484                              <1> 	;
  2485                              <1> ; 24/12/2021
  2486                              <1> ; ('swap_out' procedure call is disabled)
  2487                              <1> 
  2488                              <1> out_of_memory:
  2489                              <1> ;	call	swap_out
  2490                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2491                              <1> ;	;
  2492                              <1> ;	sub 	eax, eax ; 0
  2493 00002DF7 F9                  <1> 	stc
  2494 00002DF8 C3                  <1> 	retn
  2495                              <1> 
  2496                              <1> al_p_found:
  2497 00002DF9 89D9                <1> 	mov	ecx, ebx
  2498 00002DFB 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2499 00002E01 890D[946B0000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2500                              <1> 				 ; address/offset (to the next)
  2501 00002E07 FF0D[906B0000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2502                              <1> 	;
  2503 00002E0D 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2504                              <1> 				 ; is copied into the Carry Flag and then cleared
  2505                              <1> 				 ; in the destination.
  2506                              <1> 				 ;
  2507                              <1> 				 ; Reset the bit which is corresponding to the 
  2508                              <1> 				 ; (just) allocated page.
  2509                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2510 00002E10 C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2511 00002E13 01C8                <1> 	add	eax, ecx	 ; = page number
  2512 00002E15 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2513                              <1> 	; EAX = physical address of memory page
  2514                              <1> 	;
  2515                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2516                              <1> 	;       according to this EAX value...
  2517 00002E18 59                  <1> 	pop	ecx
  2518 00002E19 5B                  <1> 	pop	ebx
  2519                              <1> al_p_ok:
  2520 00002E1A C3                  <1> 	retn
  2521                              <1> 
  2522                              <1> make_page_dir:
  2523                              <1> 	; 18/04/2015
  2524                              <1> 	; 12/04/2015
  2525                              <1> 	; 23/10/2014
  2526                              <1> 	; 16/10/2014
  2527                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2528                              <1> 	;
  2529                              <1> 	; INPUT ->
  2530                              <1> 	;	none
  2531                              <1> 	; OUTPUT ->
  2532                              <1> 	;	(EAX = 0)
  2533                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2534                              <1> 	;	cf = 0 ->
  2535                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2536                              <1> 	;		  process/user.
  2537                              <1> 	;
  2538                              <1> 	; Modified Registers -> EAX
  2539                              <1> 	;
  2540 00002E1B E896FFFFFF          <1> 	call	allocate_page
  2541 00002E20 7216                <1> 	jc	short mkpd_error
  2542                              <1> 	;
  2543 00002E22 A3[A56F0000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2544                              <1> 				  ; (Physical address)
  2545                              <1> clear_page:
  2546                              <1> 	; 18/04/2015
  2547                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2548                              <1> 	;
  2549                              <1> 	; INPUT ->
  2550                              <1> 	;	EAX = physical address of the page
  2551                              <1> 	; OUTPUT ->
  2552                              <1> 	;	all bytes of the page will be cleared
  2553                              <1> 	;
  2554                              <1> 	; Modified Registers -> none
  2555                              <1> 	;
  2556 00002E27 57                  <1> 	push	edi
  2557 00002E28 51                  <1> 	push	ecx
  2558 00002E29 50                  <1> 	push	eax
  2559 00002E2A B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2560 00002E2F 89C7                <1> 	mov	edi, eax
  2561 00002E31 31C0                <1> 	xor	eax, eax
  2562 00002E33 F3AB                <1> 	rep	stosd
  2563 00002E35 58                  <1> 	pop	eax
  2564 00002E36 59                  <1> 	pop	ecx
  2565 00002E37 5F                  <1> 	pop	edi
  2566                              <1> mkpd_error:
  2567                              <1> mkpt_error:
  2568 00002E38 C3                  <1> 	retn
  2569                              <1> 
  2570                              <1> make_page_table:
  2571                              <1> 	; 23/06/2015
  2572                              <1> 	; 18/04/2015
  2573                              <1> 	; 12/04/2015
  2574                              <1> 	; 16/10/2014
  2575                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2576                              <1> 	;
  2577                              <1> 	; INPUT ->
  2578                              <1> 	;	EBX = virtual (linear) address
  2579                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2580                              <1> 	;	      (higher 20 bits must be ZERO)
  2581                              <1> 	;	      (bit 0 must be 1)	 
  2582                              <1> 	;	u.pgdir = page directory (physical) address
  2583                              <1> 	; OUTPUT ->
  2584                              <1> 	;	EDX = Page directory entry address
  2585                              <1> 	;	EAX = Page table address
  2586                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2587                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2588                              <1> 	;
  2589                              <1> 	; Modified Registers -> EAX, EDX
  2590                              <1> 	;
  2591 00002E39 E878FFFFFF          <1> 	call	allocate_page
  2592 00002E3E 72F8                <1> 	jc	short mkpt_error
  2593 00002E40 E811000000          <1> 	call	set_pde	
  2594 00002E45 EBE0                <1> 	jmp	short clear_page
  2595                              <1> 
  2596                              <1> make_page:
  2597                              <1> 	; 24/07/2015
  2598                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2599                              <1> 	;
  2600                              <1> 	; INPUT ->
  2601                              <1> 	;	EBX = virtual (linear) address
  2602                              <1> 	;	ECX = page attributes (lower 12 bits)
  2603                              <1> 	;	      (higher 20 bits must be ZERO)
  2604                              <1> 	;	      (bit 0 must be 1)	 
  2605                              <1> 	;	u.pgdir = page directory (physical) address
  2606                              <1> 	; OUTPUT ->
  2607                              <1> 	;	EBX = Virtual address
  2608                              <1> 	;	(EDX = PTE value)
  2609                              <1> 	;	EAX = Physical address
  2610                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2611                              <1> 	;
  2612                              <1> 	; Modified Registers -> EAX, EDX
  2613                              <1> 	;
  2614 00002E47 E86AFFFFFF          <1> 	call	allocate_page
  2615 00002E4C 7207                <1> 	jc	short mkp_err
  2616 00002E4E E821000000          <1> 	call	set_pte	
  2617 00002E53 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2618                              <1> mkp_err:
  2619 00002E55 C3                  <1> 	retn
  2620                              <1> 
  2621                              <1> set_pde:	; Set page directory entry (PDE)
  2622                              <1> 	; 20/07/2015
  2623                              <1> 	; 18/04/2015
  2624                              <1> 	; 12/04/2015
  2625                              <1> 	; 23/10/2014
  2626                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2627                              <1> 	;
  2628                              <1> 	; INPUT ->
  2629                              <1> 	;	EAX = physical address
  2630                              <1> 	;	      (use present value if EAX = 0)
  2631                              <1> 	;	EBX = virtual (linear) address
  2632                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2633                              <1> 	;	      (higher 20 bits must be ZERO)
  2634                              <1> 	;	      (bit 0 must be 1)	 
  2635                              <1> 	;	u.pgdir = page directory (physical) address
  2636                              <1> 	; OUTPUT ->
  2637                              <1> 	;	EDX = PDE address
  2638                              <1> 	;	EAX = page table address (physical)
  2639                              <1> 	;	;(CF=1 -> Invalid page address)
  2640                              <1> 	;
  2641                              <1> 	; Modified Registers -> EDX
  2642                              <1> 	;
  2643 00002E56 89DA                <1> 	mov	edx, ebx
  2644 00002E58 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2645 00002E5B C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2646 00002E5E 0315[A56F0000]      <1> 	add	edx, [u.pgdir]
  2647                              <1> 	;
  2648 00002E64 21C0                <1> 	and	eax, eax
  2649 00002E66 7506                <1> 	jnz	short spde_1
  2650                              <1> 	;
  2651 00002E68 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2652                              <1> 	;test	al, 1
  2653                              <1> 	;jz	short spde_2
  2654 00002E6A 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2655                              <1> spde_1:
  2656                              <1> 	;and	cx, 0FFFh
  2657 00002E6E 8902                <1> 	mov	[edx], eax
  2658 00002E70 66090A              <1> 	or	[edx], cx
  2659 00002E73 C3                  <1> 	retn
  2660                              <1> ;spde_2: ; error
  2661                              <1> ;	stc
  2662                              <1> ;	retn
  2663                              <1> 
  2664                              <1> set_pte:	; Set page table entry (PTE)
  2665                              <1> 	; 24/07/2015
  2666                              <1> 	; 20/07/2015
  2667                              <1> 	; 23/06/2015
  2668                              <1> 	; 18/04/2015
  2669                              <1> 	; 12/04/2015
  2670                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2671                              <1> 	;
  2672                              <1> 	; INPUT ->
  2673                              <1> 	;	EAX = physical page address
  2674                              <1> 	;	      (use present value if EAX = 0)
  2675                              <1> 	;	EBX = virtual (linear) address
  2676                              <1> 	;	ECX = page attributes (lower 12 bits)
  2677                              <1> 	;	      (higher 20 bits must be ZERO)
  2678                              <1> 	;	      (bit 0 must be 1)	 
  2679                              <1> 	;	u.pgdir = page directory (physical) address
  2680                              <1> 	; OUTPUT ->
  2681                              <1> 	;	EAX = physical page address
  2682                              <1> 	;	(EDX = PTE value)
  2683                              <1> 	;	EBX = virtual address
  2684                              <1> 	;
  2685                              <1> 	;	CF = 1 -> error
  2686                              <1> 	;
  2687                              <1> 	; Modified Registers -> EAX, EDX
  2688                              <1> 	;
  2689 00002E74 50                  <1> 	push	eax
  2690 00002E75 A1[A56F0000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2691 00002E7A E837000000          <1> 	call 	get_pde
  2692                              <1> 		; EDX = PDE address
  2693                              <1> 		; EAX = PDE value
  2694 00002E7F 5A                  <1> 	pop	edx ; physical page address
  2695 00002E80 722A                <1> 	jc	short spte_err ; PDE not present
  2696                              <1> 	;
  2697 00002E82 53                  <1> 	push	ebx ; 24/07/2015
  2698 00002E83 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2699                              <1> 			    ; EDX = PT address (physical)	
  2700 00002E87 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2701 00002E8A 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2702                              <1> 			 ; clear higher 10 bits (PD bits)
  2703 00002E90 C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2704 00002E93 01C3                <1> 	add	ebx, eax
  2705                              <1> 	;
  2706 00002E95 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2707 00002E97 A801                <1> 	test	al, 1
  2708 00002E99 740C                <1> 	jz	short spte_0
  2709 00002E9B 09D2                <1> 	or	edx, edx
  2710 00002E9D 750F                <1> 	jnz	short spte_1
  2711 00002E9F 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2712 00002EA3 89C2                <1> 	mov	edx, eax
  2713 00002EA5 EB09                <1> 	jmp	short spte_2	
  2714                              <1> spte_0:
  2715                              <1> 	; If this PTE contains a swap (disk) address,
  2716                              <1> 	; it can be updated by using 'swap_in' procedure
  2717                              <1> 	; only!
  2718 00002EA7 21C0                <1> 	and	eax, eax
  2719 00002EA9 7403                <1> 	jz	short spte_1
  2720                              <1> 	; 24/07/2015
  2721                              <1> 	; swapped page ! (on disk)
  2722 00002EAB 5B                  <1> 	pop	ebx
  2723                              <1> spte_err:
  2724 00002EAC F9                  <1> 	stc
  2725 00002EAD C3                  <1> 	retn
  2726                              <1> spte_1: 
  2727 00002EAE 89D0                <1> 	mov	eax, edx
  2728                              <1> spte_2:
  2729 00002EB0 09CA                <1> 	or	edx, ecx
  2730                              <1> 	; 23/06/2015
  2731 00002EB2 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2732                              <1> 	; 24/07/2015
  2733 00002EB4 5B                  <1> 	pop	ebx
  2734 00002EB5 C3                  <1> 	retn
  2735                              <1> 
  2736                              <1> get_pde:	; Get present value of the relevant PDE
  2737                              <1> 	; 20/07/2015
  2738                              <1> 	; 18/04/2015
  2739                              <1> 	; 12/04/2015
  2740                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2741                              <1> 	;
  2742                              <1> 	; INPUT ->
  2743                              <1> 	;	EBX = virtual (linear) address
  2744                              <1> 	;	EAX = page directory (physical) address
  2745                              <1> 	; OUTPUT ->
  2746                              <1> 	;	EDX = Page directory entry address
  2747                              <1> 	;	EAX = Page directory entry value
  2748                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2749                              <1> 	; Modified Registers -> EDX, EAX
  2750                              <1> 	;
  2751 00002EB6 89DA                <1> 	mov	edx, ebx
  2752 00002EB8 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2753 00002EBB C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2754 00002EBE 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2755 00002EC0 8B02                <1> 	mov	eax, [edx]
  2756 00002EC2 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2757 00002EC4 751F                <1> 	jnz	short gpte_retn
  2758 00002EC6 F9                  <1> 	stc
  2759                              <1> gpde_retn:	
  2760 00002EC7 C3                  <1> 	retn
  2761                              <1> 
  2762                              <1> get_pte:
  2763                              <1> 		; Get present value of the relevant PTE
  2764                              <1> 	; 29/07/2015
  2765                              <1> 	; 20/07/2015
  2766                              <1> 	; 18/04/2015
  2767                              <1> 	; 12/04/2015
  2768                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2769                              <1> 	;
  2770                              <1> 	; INPUT ->
  2771                              <1> 	;	EBX = virtual (linear) address
  2772                              <1> 	;	EAX = page directory (physical) address
  2773                              <1> 	; OUTPUT ->
  2774                              <1> 	;	EDX = Page table entry address (if CF=0)
  2775                              <1> 	;	      Page directory entry address (if CF=1)
  2776                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2777                              <1> 	;	EAX = Page table entry value (page address)
  2778                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2779                              <1> 	; Modified Registers -> EAX, EDX
  2780                              <1> 	;
  2781 00002EC8 E8E9FFFFFF          <1> 	call 	get_pde
  2782 00002ECD 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2783                              <1> 	;jnc	short gpte_1
  2784                              <1> 	;retn
  2785                              <1> ;gpte_1:
  2786 00002ECF 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2787 00002ED3 89DA                <1> 	mov	edx, ebx
  2788 00002ED5 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2789 00002ED8 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2790                              <1> 			 ; clear higher 10 bits (PD bits)
  2791 00002EDE C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2792 00002EE1 01C2                <1> 	add	edx, eax
  2793 00002EE3 8B02                <1> 	mov	eax, [edx]
  2794                              <1> gpte_retn:
  2795 00002EE5 C3                  <1> 	retn
  2796                              <1> 
  2797                              <1> deallocate_page_dir:
  2798                              <1> 	; 15/09/2015
  2799                              <1> 	; 05/08/2015
  2800                              <1> 	; 30/04/2015
  2801                              <1> 	; 28/04/2015
  2802                              <1> 	; 17/10/2014
  2803                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2804                              <1> 	;
  2805                              <1> 	; INPUT ->
  2806                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2807                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2808                              <1> 	; OUTPUT ->
  2809                              <1> 	;	All of page tables in the page directory
  2810                              <1> 	;	and page dir's itself will be deallocated
  2811                              <1> 	;	except 'read only' duplicated pages (will be converted
  2812                              <1> 	;	to writable pages).
  2813                              <1> 	;
  2814                              <1> 	; Modified Registers -> EAX
  2815                              <1> 	;
  2816                              <1> 	;
  2817 00002EE6 56                  <1> 	push	esi
  2818 00002EE7 51                  <1> 	push	ecx
  2819 00002EE8 50                  <1> 	push	eax
  2820 00002EE9 89C6                <1> 	mov	esi, eax 
  2821 00002EEB 31C9                <1> 	xor	ecx, ecx
  2822                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2823                              <1> 	; it must not be deallocated
  2824 00002EED 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2825                              <1> dapd_0:
  2826 00002EEF AD                  <1> 	lodsd
  2827 00002EF0 A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2828 00002EF2 7409                <1> 	jz	short dapd_1	
  2829 00002EF4 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2830 00002EF8 E812000000          <1> 	call	deallocate_page_table			
  2831                              <1> dapd_1:
  2832 00002EFD 41                  <1> 	inc	ecx ; page directory entry index
  2833 00002EFE 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2834 00002F04 72E9                <1> 	jb	short dapd_0
  2835                              <1> dapd_2:
  2836 00002F06 58                  <1> 	pop	eax
  2837 00002F07 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2838 00002F0C 59                  <1> 	pop	ecx
  2839 00002F0D 5E                  <1> 	pop	esi
  2840 00002F0E C3                  <1> 	retn
  2841                              <1> 
  2842                              <1> deallocate_page_table:
  2843                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2844                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2845                              <1> 	; 19/09/2015
  2846                              <1> 	; 15/09/2015
  2847                              <1> 	; 05/08/2015
  2848                              <1> 	; 30/04/2015
  2849                              <1> 	; 28/04/2015
  2850                              <1> 	; 24/10/2014
  2851                              <1> 	; 23/10/2014
  2852                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2853                              <1> 	;
  2854                              <1> 	; INPUT ->
  2855                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2856                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2857                              <1> 	;	(ECX = page directory entry index)
  2858                              <1> 	; OUTPUT ->
  2859                              <1> 	;	All of pages in the page table and page table's itself
  2860                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2861                              <1> 	;	(will be converted to writable pages).
  2862                              <1> 	;
  2863                              <1> 	; Modified Registers -> EAX
  2864                              <1> 	;
  2865 00002F0F 56                  <1> 	push	esi
  2866 00002F10 57                  <1> 	push	edi
  2867 00002F11 52                  <1> 	push	edx
  2868 00002F12 50                  <1> 	push	eax ; *
  2869 00002F13 89C6                <1> 	mov	esi, eax 
  2870 00002F15 31FF                <1> 	xor	edi, edi ; 0
  2871                              <1> dapt_0:
  2872 00002F17 AD                  <1> 	lodsd
  2873 00002F18 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2874 00002F1A 7455                <1> 	jz	short dapt_1
  2875                              <1> 	;
  2876 00002F1C A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2877                              <1> 				  ; (must be 1)
  2878 00002F1E 753F                <1> 	jnz	short dapt_3
  2879                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2880 00002F20 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2881                              <1> 				   ; as child's page ?
  2882 00002F24 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2883                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2884                              <1> 	; ECX = page directory entry index (0-1023)
  2885 00002F26 53                  <1> 	push	ebx
  2886 00002F27 51                  <1> 	push	ecx
  2887 00002F28 66C1E102            <1> 	shl	cx, 2 ; *4 
  2888 00002F2C 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2889 00002F2E 8B0B                <1> 	mov	ecx, [ebx]
  2890 00002F30 F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2891 00002F33 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2892 00002F35 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2893                              <1> 	; EDI = page table entry index (0-1023)
  2894 00002F3A 89FA                <1> 	mov	edx, edi 
  2895 00002F3C 66C1E202            <1> 	shl	dx, 2 ; *4 
  2896 00002F40 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2897 00002F42 8B1A                <1> 	mov	ebx, [edx]
  2898 00002F44 F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2899 00002F47 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2900 00002F49 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2901 00002F4D 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2902 00002F52 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2903 00002F54 7507                <1> 	jne	short dapt_2	; not same page
  2904                              <1> 				; deallocate the child's page
  2905 00002F56 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2906 00002F59 59                  <1> 	pop	ecx
  2907 00002F5A 5B                  <1> 	pop	ebx
  2908 00002F5B EB0D                <1> 	jmp	short dapt_4
  2909                              <1> 
  2910                              <1> ; 24/12/2021
  2911                              <1> ; ('dapt_1' is disabled)
  2912                              <1> ;
  2913                              <1> ;dapt_1:
  2914                              <1> ;	or	eax, eax	; swapped page ?
  2915                              <1> ;	jz	short dapt_5	; no
  2916                              <1> ;				; yes
  2917                              <1> ;	shr	eax, 1
  2918                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2919                              <1> ;				  ; on the swap disk (or in file)
  2920                              <1> ;	jmp	short dapt_5
  2921                              <1> dapt_2:
  2922 00002F5D 59                  <1> 	pop	ecx
  2923 00002F5E 5B                  <1> 	pop	ebx
  2924                              <1> dapt_3:	
  2925                              <1> 	; 12/07/2016
  2926 00002F5F 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2927 00002F63 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2928                              <1> 	;
  2929                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2930 00002F65 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2931                              <1> dapt_4:
  2932 00002F6A C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2933                              <1> dapt_1:	; 24/12/2021
  2934                              <1> dapt_5:
  2935 00002F71 47                  <1> 	inc	edi ; page table entry index
  2936 00002F72 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2937 00002F78 729D                <1> 	jb	short dapt_0
  2938                              <1> 	;
  2939 00002F7A 58                  <1> 	pop	eax ; *
  2940 00002F7B 5A                  <1> 	pop	edx
  2941 00002F7C 5F                  <1> 	pop	edi	
  2942 00002F7D 5E                  <1> 	pop	esi
  2943                              <1> 	;
  2944                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2945                              <1> 	;retn
  2946                              <1> 
  2947                              <1> deallocate_page:
  2948                              <1> 	; 15/09/2015
  2949                              <1> 	; 28/04/2015
  2950                              <1> 	; 10/03/2015
  2951                              <1> 	; 17/10/2014
  2952                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2953                              <1> 	;
  2954                              <1> 	; INPUT -> 
  2955                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2956                              <1> 	; OUTPUT ->
  2957                              <1> 	;	[free_pages] is increased
  2958                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2959                              <1> 	;	CF = 1 if the page is already deallocated
  2960                              <1> 	; 	       (or not allocated) before.  
  2961                              <1> 	;
  2962                              <1> 	; Modified Registers -> EAX
  2963                              <1> 	;
  2964 00002F7E 53                  <1> 	push	ebx
  2965 00002F7F 52                  <1> 	push	edx
  2966                              <1> 	;
  2967 00002F80 C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2968                              <1> 				     ; 12 bits right
  2969                              <1> 				     ; to get page number
  2970 00002F83 89C2                <1> 	mov	edx, eax
  2971                              <1> 	; 15/09/2015
  2972 00002F85 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2973                              <1> 				     ; (1 allocation bit = 1 page)
  2974                              <1> 				     ; (1 allocation bytes = 8 pages)
  2975 00002F88 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2976                              <1> 				     ; (to get 32 bit position)			
  2977                              <1> 	;
  2978 00002F8B BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2979 00002F90 01D3                <1> 	add	ebx, edx
  2980 00002F92 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2981                              <1> 				     ; (allocation bit position)	 
  2982 00002F95 3B15[946B0000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2983                              <1> 				     ; than the address in 'next_page' ?
  2984                              <1> 				     ; (next/first free page value)		
  2985 00002F9B 7306                <1> 	jnb	short dap_1	     ; no	
  2986 00002F9D 8915[946B0000]      <1> 	mov	[next_page], edx     ; yes
  2987                              <1> dap_1:
  2988 00002FA3 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2989                              <1> 				     ; set relevant bit to 1.
  2990                              <1> 				     ; set CF to the previous bit value	
  2991                              <1> 	;cmc			     ; complement carry flag	
  2992                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2993                              <1> 				     ; if the page is already deallocated
  2994                              <1> 				     ; before.	
  2995 00002FA6 FF05[906B0000]      <1>         inc     dword [free_pages]
  2996                              <1> dap_2:
  2997 00002FAC 5A                  <1> 	pop	edx
  2998 00002FAD 5B                  <1> 	pop	ebx
  2999 00002FAE C3                  <1> 	retn
  3000                              <1> 
  3001                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3002                              <1> ;;                                                              ;;
  3003                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  3004                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  3005                              <1> ;;                                                              ;;
  3006                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3007                              <1> 
  3008                              <1> ;;$Revision: 5057 $
  3009                              <1> 
  3010                              <1> 
  3011                              <1> ;;align 4
  3012                              <1> ;;proc alloc_page
  3013                              <1> 
  3014                              <1> ;;        pushfd
  3015                              <1> ;;        cli
  3016                              <1> ;;        push    ebx
  3017                              <1> ;;;//-
  3018                              <1> ;;        cmp     [pg_data.pages_free], 1
  3019                              <1> ;;        jle     .out_of_memory
  3020                              <1> ;;;//-
  3021                              <1> ;;
  3022                              <1> ;;        mov     ebx, [page_start]
  3023                              <1> ;;        mov     ecx, [page_end]
  3024                              <1> ;;.l1:
  3025                              <1> ;;        bsf     eax, [ebx];
  3026                              <1> ;;        jnz     .found
  3027                              <1> ;;        add     ebx, 4
  3028                              <1> ;;        cmp     ebx, ecx
  3029                              <1> ;;        jb      .l1
  3030                              <1> ;;        pop     ebx
  3031                              <1> ;;        popfd
  3032                              <1> ;;        xor     eax, eax
  3033                              <1> ;;        ret
  3034                              <1> ;;.found:
  3035                              <1> ;;;//-
  3036                              <1> ;;        dec     [pg_data.pages_free]
  3037                              <1> ;;        jz      .out_of_memory
  3038                              <1> ;;;//-
  3039                              <1> ;;        btr     [ebx], eax
  3040                              <1> ;;        mov     [page_start], ebx
  3041                              <1> ;;        sub     ebx, sys_pgmap
  3042                              <1> ;;        lea     eax, [eax+ebx*8]
  3043                              <1> ;;        shl     eax, 12
  3044                              <1> ;;;//-       dec [pg_data.pages_free]
  3045                              <1> ;;        pop     ebx
  3046                              <1> ;;        popfd
  3047                              <1> ;;        ret
  3048                              <1> ;;;//-
  3049                              <1> ;;.out_of_memory:
  3050                              <1> ;;        mov     [pg_data.pages_free], 1
  3051                              <1> ;;        xor     eax, eax
  3052                              <1> ;;        pop     ebx
  3053                              <1> ;;        popfd
  3054                              <1> ;;        ret
  3055                              <1> ;;;//-
  3056                              <1> ;;endp
  3057                              <1> 
  3058                              <1> duplicate_page_dir:
  3059                              <1> 	; 21/09/2015
  3060                              <1> 	; 31/08/2015
  3061                              <1> 	; 20/07/2015
  3062                              <1> 	; 28/04/2015
  3063                              <1> 	; 27/04/2015
  3064                              <1> 	; 18/04/2015
  3065                              <1> 	; 12/04/2015
  3066                              <1> 	; 18/10/2014
  3067                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3068                              <1> 	;
  3069                              <1> 	; INPUT -> 
  3070                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3071                              <1> 	;		    page directory.
  3072                              <1> 	; OUTPUT ->
  3073                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3074                              <1> 	;	       page directory.
  3075                              <1> 	;	(New page directory with new page table entries.)
  3076                              <1> 	;	(New page tables with read only copies of the parent's
  3077                              <1> 	;	pages.)
  3078                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3079                              <1> 	;
  3080                              <1> 	; Modified Registers -> none (except EAX)
  3081                              <1> 	;
  3082 00002FAF E802FEFFFF          <1> 	call	allocate_page
  3083 00002FB4 723E                <1> 	jc	short dpd_err
  3084                              <1> 	;
  3085 00002FB6 55                  <1> 	push	ebp ; 20/07/2015
  3086 00002FB7 56                  <1> 	push	esi
  3087 00002FB8 57                  <1> 	push	edi
  3088 00002FB9 53                  <1> 	push	ebx
  3089 00002FBA 51                  <1> 	push	ecx
  3090 00002FBB 8B35[A56F0000]      <1> 	mov	esi, [u.pgdir]
  3091 00002FC1 89C7                <1> 	mov	edi, eax
  3092 00002FC3 50                  <1> 	push	eax ; save child's page directory address
  3093                              <1> 	; 31/08/2015
  3094                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3095                              <1> 	; (use same system space for all user page tables) 
  3096 00002FC4 A5                  <1> 	movsd
  3097 00002FC5 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3098 00002FCA B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3099                              <1> dpd_0:	
  3100 00002FCF AD                  <1> 	lodsd
  3101                              <1> 	;or	eax, eax
  3102                              <1>         ;jnz     short dpd_1
  3103 00002FD0 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3104 00002FD2 7508                <1> 	jnz	short dpd_1
  3105                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3106 00002FD4 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3107 00002FDA EB0F                <1> 	jmp	short dpd_2
  3108                              <1> dpd_1:	
  3109 00002FDC 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3110 00002FE0 89C3                <1> 	mov	ebx, eax
  3111                              <1> 	; EBX = Parent's page table address
  3112 00002FE2 E81F000000          <1> 	call	duplicate_page_table
  3113 00002FE7 720C                <1> 	jc	short dpd_p_err
  3114                              <1> 	; EAX = Child's page table address
  3115 00002FE9 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3116                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3117                              <1> 			 ; (present, writable, user)
  3118                              <1> dpd_2:
  3119 00002FEB AB                  <1> 	stosd
  3120 00002FEC E2E1                <1> 	loop	dpd_0
  3121                              <1> 	;
  3122 00002FEE 58                  <1> 	pop	eax  ; restore child's page directory address
  3123                              <1> dpd_3:
  3124 00002FEF 59                  <1> 	pop	ecx
  3125 00002FF0 5B                  <1> 	pop	ebx
  3126 00002FF1 5F                  <1> 	pop	edi
  3127 00002FF2 5E                  <1> 	pop	esi
  3128 00002FF3 5D                  <1> 	pop	ebp ; 20/07/2015
  3129                              <1> dpd_err:
  3130 00002FF4 C3                  <1> 	retn
  3131                              <1> dpd_p_err:
  3132                              <1> 	; release the allocated pages missing (recover free space)
  3133 00002FF5 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3134 00002FF6 8B1D[A56F0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3135 00002FFC E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3136 00003001 29C0                <1> 	sub	eax, eax ; 0
  3137 00003003 F9                  <1> 	stc
  3138 00003004 EBE9                <1> 	jmp	short dpd_3	
  3139                              <1> 
  3140                              <1> duplicate_page_table:
  3141                              <1> 	; 31/12/2021
  3142                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3143                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3144                              <1> 	; 21/09/2015
  3145                              <1> 	; 20/07/2015
  3146                              <1> 	; 05/05/2015
  3147                              <1> 	; 28/04/2015
  3148                              <1> 	; 27/04/2015
  3149                              <1> 	; 18/04/2015
  3150                              <1> 	; 18/10/2014
  3151                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3152                              <1> 	;
  3153                              <1> 	; INPUT -> 
  3154                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3155                              <1> 	;       20/02/2017		 
  3156                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3157                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3158                              <1> 	; OUTPUT ->
  3159                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3160                              <1> 	;	      (with 'read only' attribute of page table entries)
  3161                              <1> 	;	20/02/2017
  3162                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3163                              <1> 	;	
  3164                              <1> 	;	CF = 1 -> error 
  3165                              <1> 	;
  3166                              <1> 	; Modified Registers -> EBP (except EAX)
  3167                              <1> 	;
  3168 00003006 E8ABFDFFFF          <1> 	call	allocate_page
  3169 0000300B 725B                <1> 	jc	short dpt_err
  3170                              <1> 	;
  3171 0000300D 50                  <1> 	push	eax ; *
  3172 0000300E 56                  <1> 	push	esi
  3173 0000300F 57                  <1> 	push	edi
  3174 00003010 52                  <1> 	push	edx
  3175 00003011 51                  <1> 	push	ecx
  3176                              <1> 	;
  3177 00003012 89DE                <1> 	mov	esi, ebx
  3178 00003014 89C7                <1> 	mov	edi, eax
  3179 00003016 89C2                <1> 	mov	edx, eax
  3180 00003018 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3181                              <1> dpt_0:
  3182 0000301E AD                  <1> 	lodsd
  3183 0000301F 21C0                <1> 	and	eax, eax
  3184 00003021 7435                <1> 	jz	short dpt_3
  3185 00003023 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3186                              <1> 	; 24/12/2021
  3187 00003025 7503                <1> 	jnz	short dpt_1
  3188                              <1> 	;jz	short dpt_p_err
  3189                              <1> 	; 31/12/2021
  3190 00003027 F9                  <1> 	stc
  3191 00003028 EB39                <1> 	jmp	short dpt_p_err
  3192                              <1> 
  3193                              <1> ; 24/12/2021
  3194                              <1> ; ('reload_page' procedure call is disabled)
  3195                              <1> ;
  3196                              <1> ;	; 20/07/2015
  3197                              <1> ;	; ebp = virtual (linear) address of the memory page
  3198                              <1> ;	call	reload_page ; 28/04/2015
  3199                              <1> ;	jc	short dpt_p_err
  3200                              <1> dpt_1:
  3201                              <1> 	; 21/09/2015
  3202 0000302A 89C1                <1> 	mov	ecx, eax
  3203 0000302C 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3204 00003030 F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3205 00003033 751A                <1> 	jnz	short dpt_2
  3206                              <1> 	; Read only (parent) page
  3207                              <1> 	; 	- there is a third process which uses this page -
  3208                              <1> 	; Allocate a new page for the child process
  3209 00003035 E87CFDFFFF          <1> 	call	allocate_page
  3210 0000303A 7227                <1> 	jc	short dpt_p_err
  3211 0000303C 57                  <1> 	push	edi
  3212 0000303D 56                  <1> 	push	esi
  3213 0000303E 89CE                <1> 	mov	esi, ecx
  3214 00003040 89C7                <1> 	mov	edi, eax
  3215 00003042 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3216 00003047 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3217 00003049 5E                  <1> 	pop	esi
  3218 0000304A 5F                  <1> 	pop	edi
  3219                              <1> 	;
  3220                              <1> 
  3221                              <1> ; 24/12/2021
  3222                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3223                              <1> ; 
  3224                              <1> ;	push	ebx
  3225                              <1> ;	push	eax
  3226                              <1> ;	; 20/07/2015
  3227                              <1> ;	mov	ebx, ebp
  3228                              <1> ;	; ebx = virtual (linear) address of the memory page
  3229                              <1> ;	call	add_to_swap_queue
  3230                              <1> ;	pop	eax
  3231                              <1> ;	pop	ebx
  3232                              <1> 
  3233                              <1> 	; 21/09/2015
  3234 0000304B 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3235                              <1> 		; user + writable + present page
  3236 0000304D EB09                <1> 	jmp	short dpt_3
  3237                              <1> dpt_2:
  3238                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3239 0000304F 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3240                              <1> 		    ; (read only page!)
  3241 00003051 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3242 00003054 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3243                              <1> dpt_3:
  3244 00003058 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3245                              <1> 	;
  3246 00003059 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3247                              <1> 	;
  3248 0000305F 39D7                <1> 	cmp	edi, edx
  3249 00003061 72BB                <1> 	jb	short dpt_0
  3250                              <1> dpt_p_err:
  3251 00003063 59                  <1> 	pop	ecx
  3252 00003064 5A                  <1> 	pop	edx
  3253 00003065 5F                  <1> 	pop	edi
  3254 00003066 5E                  <1> 	pop	esi
  3255 00003067 58                  <1> 	pop	eax ; *
  3256                              <1> dpt_err:
  3257 00003068 C3                  <1> 	retn
  3258                              <1> 
  3259                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3260                              <1> 	; 31/12/2021
  3261                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3262                              <1> 	; 21/09/2015
  3263                              <1> 	; 19/09/2015
  3264                              <1> 	; 17/09/2015
  3265                              <1> 	; 28/08/2015
  3266                              <1> 	; 20/07/2015
  3267                              <1> 	; 28/06/2015
  3268                              <1> 	; 03/05/2015
  3269                              <1> 	; 30/04/2015
  3270                              <1> 	; 18/04/2015
  3271                              <1> 	; 12/04/2015
  3272                              <1> 	; 30/10/2014
  3273                              <1> 	; 11/09/2014
  3274                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3275                              <1> 	;
  3276                              <1> 	; Note: This is not an interrupt/exception handler.
  3277                              <1> 	;	This is a 'page fault remedy' subroutine 
  3278                              <1> 	;	which will be called by standard/uniform
  3279                              <1> 	;	exception handler.
  3280                              <1> 	;
  3281                              <1> 	; INPUT -> 
  3282                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3283                              <1> 	;
  3284                              <1> 	;	cr2 = the virtual (linear) address 
  3285                              <1> 	;	      which has caused to page fault (19/09/2015)
  3286                              <1> 	;
  3287                              <1> 	; OUTPUT ->
  3288                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3289                              <1> 	;	EAX = 0 -> no error
  3290                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3291                              <1> 	;
  3292                              <1> 	; Modified Registers -> none (except EAX)
  3293                              <1> 	;	
  3294                              <1>         ;
  3295                              <1>         ; ERROR CODE:
  3296                              <1> 	;	 31  .....	4   3	2   1	0
  3297                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3298                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3299                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3300                              <1> 	;
  3301                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3302                              <1>     	;		a page-protection violation. When not set,
  3303                              <1> 	;		it was caused by a non-present page.
  3304                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3305                              <1> 	;		a page write. When not set, it was caused
  3306                              <1> 	;		by a page read.
  3307                              <1> 	; U : USER    -	When set, the page fault was caused 
  3308                              <1> 	;		while CPL = 3. 
  3309                              <1> 	;		This does not necessarily mean that
  3310                              <1> 	;		the page fault was a privilege violation.
  3311                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3312                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3313                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3314                              <1> 	;     FETCH	an instruction fetch
  3315                              <1> 	;
  3316                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3317                              <1> 	;  31               22                  12 11                    0
  3318                              <1> 	; +-------------------+-------------------+-----------------------+
  3319                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3320                              <1>        	; +-------------------+-------------------+-----------------------+
  3321                              <1> 	;
  3322                              <1> 
  3323                              <1> 	;; CR3 REGISTER (Control Register 3)
  3324                              <1> 	;  31                                   12             5 4 3 2   0
  3325                              <1> 	; +---------------------------------------+-------------+---+-----+
  3326                              <1>       	; |                                       |  		|P|P|     |
  3327                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3328                              <1>       	; |                                       | 		|D|T|     |
  3329                              <1>    	; +---------------------------------------+-------------+---+-----+
  3330                              <1> 	;
  3331                              <1> 	;	PWT    - WRITE THROUGH
  3332                              <1> 	;	PCD    - CACHE DISABLE		
  3333                              <1> 	;
  3334                              <1> 	;
  3335                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3336                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3337                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3338                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3339                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3340                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3341                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3342                              <1> 	;
  3343                              <1>         ;       P      - PRESENT
  3344                              <1>         ;       R/W    - READ/WRITE
  3345                              <1>         ;       U/S    - USER/SUPERVISOR
  3346                              <1> 	;	PWT    - WRITE THROUGH
  3347                              <1> 	;	PCD    - CACHE DISABLE	
  3348                              <1> 	;	A      - ACCESSED	
  3349                              <1>         ;       D      - DIRTY (IGNORED)
  3350                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3351                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3352                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3353                              <1> 	;
  3354                              <1> 	;
  3355                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3356                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3357                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3358                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3359                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3360                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3361                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3362                              <1> 	;
  3363                              <1>         ;       P      - PRESENT
  3364                              <1>         ;       R/W    - READ/WRITE
  3365                              <1>         ;       U/S    - USER/SUPERVISOR
  3366                              <1> 	;	PWT    - WRITE THROUGH
  3367                              <1> 	;	PCD    - CACHE DISABLE	
  3368                              <1> 	;	A      - ACCESSED	
  3369                              <1>         ;       D      - DIRTY
  3370                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3371                              <1> 	;	G      - GLOBAL	 
  3372                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3373                              <1> 	;
  3374                              <1> 	;
  3375                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3376                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3377                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3378                              <1>       	; |                                       |     | | | | | | |U|R| |
  3379                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3380                              <1>       	; |                                       |     | | | | | | |S|W| |
  3381                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3382                              <1> 	;
  3383                              <1>         ;       P      - PRESENT
  3384                              <1>         ;       R/W    - READ/WRITE
  3385                              <1>         ;       U/S    - USER/SUPERVISOR
  3386                              <1>         ;       D      - DIRTY
  3387                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3388                              <1> 	;
  3389                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3390                              <1> 	;
  3391                              <1> 	;
  3392                              <1> 	;; Invalid Page Table Entry
  3393                              <1> 	; 31                                                           1 0
  3394                              <1>       	; +-------------------------------------------------------------+-+
  3395                              <1>       	; |                                                             | |
  3396                              <1>       	; |                          AVAILABLE                          |0|
  3397                              <1>       	; |                                                             | |
  3398                              <1>       	; +-------------------------------------------------------------+-+
  3399                              <1> 	;
  3400                              <1> 
  3401 00003069 53                  <1> 	push	ebx
  3402 0000306A 52                  <1> 	push	edx
  3403 0000306B 51                  <1> 	push	ecx
  3404                              <1> 	;
  3405                              <1> 	; 21/09/2015 (debugging)
  3406 0000306C FF05[B56F0000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3407 00003072 FF05[406C0000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3408                              <1> 	; 28/06/2015
  3409                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3410 00003078 8A15[386C0000]      <1> 	mov	dl, [error_code]
  3411                              <1> 	;
  3412 0000307E F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3413                              <1> 			; sign
  3414 00003081 7425                <1> 	jz	short pfh_alloc_np
  3415                              <1> 	; 
  3416                              <1> 	; If it is not a 'write on read only page' type page fault
  3417                              <1> 	; major page fault error with minor reason must be returned without 
  3418                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3419                              <1> 	; after return here!
  3420                              <1> 	; Page fault will be remedied, by copying page contents
  3421                              <1> 	; to newly allocated page with write permission;
  3422                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3423                              <1> 	; used for working with minimum possible memory usage. 
  3424                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3425                              <1> 	; process with 'read only' flag. If the child process attempts to
  3426                              <1> 	; write on these read only pages, page fault will be directed here
  3427                              <1> 	; for allocating a new page with same data/content. 
  3428                              <1> 	;
  3429                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3430                              <1> 	; will not force to separate CODE and DATA space 
  3431                              <1> 	; in a process/program... 
  3432                              <1> 	; CODE segment/section may contain DATA!
  3433                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3434                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3435                              <1> 	;	
  3436 00003083 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3437                              <1> 			; sign
  3438 00003086 7418                <1>         jz      pfh_p_err
  3439                              <1> 	; 31/08/2015
  3440 00003088 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3441                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3442 0000308B 7413                <1>         jz	short pfh_pv_err
  3443                              <1> 	;
  3444                              <1> 	; make a new page and copy the parent's page content
  3445                              <1> 	; as the child's new page content
  3446                              <1> 	;
  3447 0000308D 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3448                              <1> 			 ; which has caused to page fault
  3449 00003090 E87C000000          <1> 	call 	copy_page
  3450 00003095 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3451                              <1> 	;
  3452 00003097 EB72                <1>         jmp     pfh_cpp_ok
  3453                              <1> 
  3454                              <1> 	; 31/12/2021 (short jump)
  3455                              <1> pfh_im_err:
  3456 00003099 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3457                              <1> 			; Major (Primary) Error: Page Fault
  3458                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3459 0000309E EB6D                <1> 	jmp	short pfh_err_retn
  3460                              <1> 
  3461                              <1> 	; 31/12/2021
  3462                              <1> pfh_p_err: ; 09/03/2015
  3463                              <1> pfh_pv_err:
  3464                              <1> 	; Page fault was caused by a protection-violation
  3465 000030A0 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3466                              <1> 			; Major (Primary) Error: Page Fault
  3467                              <1> 			; Minor (Secondary) Error: Protection violation !
  3468 000030A5 F9                  <1> 	stc
  3469 000030A6 EB65                <1> 	jmp	short pfh_err_retn
  3470                              <1> 	
  3471                              <1> pfh_alloc_np:
  3472 000030A8 E809FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3473 000030AD 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3474                              <1> pfh_chk_cpl:
  3475                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3476                              <1> 		; (Lower 12 bits are ZERO, because 
  3477                              <1> 		;	the address is on a page boundary)
  3478 000030AF 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3479 000030B2 7505                <1> 	jnz	short pfh_um
  3480                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3481 000030B4 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3482                              <1> 			 ; of the current/active page directory
  3483                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3484                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3485 000030B7 EB06                <1> 	jmp	short pfh_get_pde
  3486                              <1> 	;
  3487                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3488 000030B9 8B1D[A56F0000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3489                              <1> 			; Physical address of the USER's page directory
  3490                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3491                              <1> pfh_get_pde:
  3492 000030BF 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3493 000030C2 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3494                              <1> 			 ; which has been caused to page fault
  3495                              <1> 			 ;
  3496 000030C5 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3497 000030C8 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3498                              <1> 	;
  3499 000030CB 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3500 000030CD 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3501 000030CF F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3502 000030D2 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3503                              <1> 			  	  ; set/validate page directory entry
  3504 000030D4 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3505 000030D9 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3506 000030DB 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3507 000030DD EB16                <1> 	jmp	short pfh_get_pte
  3508                              <1> pfh_set_pde:
  3509                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3510                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3511                              <1> 	;
  3512 000030DF 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3513 000030E1 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3514 000030E3 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3515 000030E5 89C3                <1> 	mov	ebx, eax
  3516 000030E7 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3517 000030EC 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3518                              <1> pfh_spde_1:
  3519                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3520 000030EE 89C1                <1> 	mov	ecx, eax
  3521 000030F0 E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3522                              <1> pfh_get_pte:
  3523 000030F5 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3524                              <1> 			 ; which has been caused to page fault
  3525 000030F8 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3526 000030FA C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3527                              <1> 			 ; higher 20 bits of the page fault address 
  3528 000030FD 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3529 00003102 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3530 00003105 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3531                              <1> ; 24/12/2021
  3532                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3533                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3534                              <1> ; 24/12/2021
  3535                              <1> ; ('swap_in' procedure call has been disabled)
  3536                              <1> ;
  3537                              <1> ;	and	eax, eax
  3538                              <1> ;	jz	short pfh_gpte_1
  3539                              <1> ;	; 20/07/2015
  3540                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3541                              <1> ;	push	ebp ; 20/07/2015
  3542                              <1> ;	mov	ebp, cr2
  3543                              <1> ;		; ECX = physical address of the page table entry
  3544                              <1> ;		; EBX = Memory page address (physical!)
  3545                              <1> ;		; EAX = Swap disk (offset) address
  3546                              <1> ;		; EBP = virtual address (page fault address)
  3547                              <1> ;	call	swap_in
  3548                              <1> ;	pop	ebp
  3549                              <1> ;	jc      short pfh_err_retn
  3550                              <1> ;	xchg	ecx, ebx
  3551                              <1> ;		; EBX = physical address of the page table entry
  3552                              <1> ;		; ECX = new page
  3553                              <1> pfh_gpte_1:
  3554 00003107 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3555 00003109 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3556                              <1> pfh_cpp_ok:
  3557                              <1> ; 24/12/2021
  3558                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3559                              <1> ;
  3560                              <1> ;	; 20/07/2015
  3561                              <1> ;	mov	ebx, cr2
  3562                              <1> ;	call 	add_to_swap_queue
  3563                              <1> 	;
  3564                              <1> 	; The new PTE (which contains the new page) will be added to 
  3565                              <1> 	; the swap queue, here. 
  3566                              <1> 	; (Later, if memory will become insufficient, 
  3567                              <1> 	; one page will be swapped out which is at the head of 
  3568                              <1> 	; the swap queue by using FIFO and access check methods.)
  3569                              <1> 	;
  3570 0000310B 31C0                <1> 	xor	eax, eax  ; 0
  3571                              <1> 	;
  3572                              <1> pfh_err_retn:
  3573 0000310D 59                  <1> 	pop	ecx
  3574 0000310E 5A                  <1> 	pop	edx
  3575 0000310F 5B                  <1> 	pop	ebx
  3576 00003110 C3                  <1> 	retn 
  3577                              <1> 	
  3578                              <1> copy_page:
  3579                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3580                              <1> 	; 16/04/2021
  3581                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3582                              <1> 	; 22/09/2015
  3583                              <1> 	; 21/09/2015
  3584                              <1> 	; 19/09/2015
  3585                              <1> 	; 07/09/2015
  3586                              <1> 	; 31/08/2015
  3587                              <1> 	; 20/07/2015
  3588                              <1> 	; 05/05/2015
  3589                              <1> 	; 03/05/2015
  3590                              <1> 	; 18/04/2015
  3591                              <1> 	; 12/04/2015
  3592                              <1> 	; 30/10/2014
  3593                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3594                              <1> 	;
  3595                              <1> 	; INPUT -> 
  3596                              <1> 	;	EBX = Virtual (linear) address of source page
  3597                              <1> 	;	     (Page fault address)
  3598                              <1> 	; OUTPUT ->
  3599                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3600                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3601                              <1> 	;	EAX = 0 (CF = 1) 
  3602                              <1> 	;		if there is not a free page to be allocated
  3603                              <1> 	;	(page content of the source page will be copied
  3604                              <1> 	;	onto the target/new page) 	
  3605                              <1> 	;
  3606                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3607                              <1> 	;
  3608                              <1> 
  3609                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3610                              <1> 	; INPUT: 
  3611                              <1> 	;	EBX = Virtual (linear) address of source page
  3612                              <1> 	;	     (Page fault address)
  3613                              <1> 	; OUTPUT:
  3614                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3615                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3616                              <1> 	;	EAX = 0 (CF = 1) 
  3617                              <1> 	;		if there is not a free page to be allocated
  3618                              <1> 	;	(page content of the source page will be copied
  3619                              <1> 	;	onto the target/new page) 	
  3620                              <1> 	;
  3621                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3622                              <1> 	
  3623 00003111 56                  <1> 	push	esi ; *
  3624 00003112 57                  <1> 	push	edi ; **
  3625                              <1> 	; 16/04/2021
  3626                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3627                              <1> 	;push	ebx ; ***
  3628                              <1> 	;push	ecx ; ****
  3629 00003113 31F6                <1> 	xor 	esi, esi
  3630 00003115 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3631 00003118 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3632 0000311A C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3633 0000311D 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3634 00003120 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3635 00003122 031D[A56F0000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3636 00003128 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3637 0000312A 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3638 0000312E 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3639 00003130 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3640 00003136 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3641 0000313A 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3642                              <1> 	; 07/09/2015
  3643 0000313C 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3644                              <1> 				     ; read only page as a child process?)	
  3645 00003141 7509                <1> 	jnz	short cpp_0 ; yes
  3646 00003143 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3647 00003145 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3648 0000314A EB32                <1> 	jmp	short cpp_1
  3649                              <1> cpp_0:
  3650 0000314C 89FE                <1> 	mov	esi, edi
  3651 0000314E 0335[A96F0000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3652 00003154 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3653 00003156 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3654 0000315A 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3655 0000315C 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3656 00003162 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3657 00003166 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3658 00003168 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3659                              <1> 	; 21/09/2015
  3660 0000316A 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3661 0000316C 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3662                              <1> 	;
  3663 00003170 F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3664 00003173 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3665                              <1> 	;
  3666 00003175 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3667 0000317A 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3668 0000317C 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3669                              <1> 			    ; Convert child's page to writable page
  3670                              <1> cpp_1:
  3671 0000317E E833FCFFFF          <1> 	call	allocate_page
  3672 00003183 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3673 00003185 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3674 00003187 7405                <1> 	jz	short cpp_2
  3675                              <1> 		; Convert read only page to writable page 
  3676                              <1> 		;(for the parent of the current process)
  3677                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3678                              <1> 	; 22/09/2015
  3679 00003189 890E                <1> 	mov	[esi], ecx
  3680 0000318B 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3681                              <1> 				 ; 1+2+4 = 7
  3682                              <1> cpp_2:
  3683 0000318E 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3684                              <1> 	; 07/09/2015
  3685 00003190 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3686 00003192 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3687 00003197 F3A5                <1> 	rep	movsd ; 31/08/2015
  3688                              <1> cpp_3:		
  3689 00003199 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3690 0000319B 8903                <1> 	mov	[ebx], eax ; Update PTE
  3691 0000319D 28C0                <1> 	sub	al, al ; clear attributes
  3692                              <1> cpp_4:
  3693                              <1> 	; 16/04/2021
  3694                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3695                              <1> 	;pop	ecx ; ****
  3696                              <1> 	;pop	ebx ; ***
  3697 0000319F 5F                  <1> 	pop	edi ; **
  3698 000031A0 5E                  <1> 	pop	esi ; *
  3699 000031A1 C3                  <1> 	retn
  3700                              <1> 
  3701                              <1> ;; 28/04/2015
  3702                              <1> ;; 24/10/2014
  3703                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3704                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3705                              <1> ;;
  3706                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3707                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3708                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3709                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3710                              <1> ;;
  3711                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3712                              <1> ;;
  3713                              <1> ;; Method:
  3714                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3715                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3716                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3717                              <1> ;;	When a new page is being allocated, swap queue is updated
  3718                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3719                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3720                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3721                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3722                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3723                              <1> ;;	offset value becomes it's previous offset value - 4.
  3724                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3725                              <1> ;;	the queue/list is not shifted.
  3726                              <1> ;;	After the queue/list shift, newly allocated page is added
  3727                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3728                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3729                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3730                              <1> ;;	
  3731                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3732                              <1> ;;	the first non-accessed, writable page in the list, 
  3733                              <1> ;;	from the head to the tail. The list is shifted to left 
  3734                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3735                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3736                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3737                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3738                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3739                              <1> ;;	procedure will be failed)...
  3740                              <1> ;;
  3741                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3742                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3743                              <1> ;;	(PTE) will be added to the tail of the queue after
  3744                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3745                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3746                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3747                              <1> ;;
  3748                              <1> ;;
  3749                              <1> ;;	
  3750                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3751                              <1> ;;
  3752                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3753                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3754                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3755                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3756                              <1> ;;
  3757                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3758                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3759                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3760                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3761                              <1> ;; 		 (entire swap space must be accessed by using
  3762                              <1> ;;		 31 bit offset address) 
  3763                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3764                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3765                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3766                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3767                              <1> ;;
  3768                              <1> ;; 					
  3769                              <1> ;; Method:
  3770                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3771                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3772                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3773                              <1> ;;	Swapping out is performed by using swap page queue.
  3774                              <1> ;;
  3775                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3776                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3777                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3778                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3779                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3780                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3781                              <1> ;;	calculated by adding offset value to the swap partition's 
  3782                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3783                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3784                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3785                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3786                              <1> ;;	is in a partitioned virtual hard disk.) 
  3787                              <1> ;;
  3788                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3789                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3790                              <1> ;;
  3791                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3792                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3793                              <1> ;;
  3794                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3795                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3796                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3797                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3798                              <1> ;;	it means relevant (respective) block is in use, and, 
  3799                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3800                              <1> ;;      swap disk/file block is free.
  3801                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3802                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3803                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3804                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3805                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3806                              <1> ;;	------------------------------------------------------------
  3807                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3808                              <1> ;;	------------------------------------------------------------
  3809                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3810                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3811                              <1> ;;
  3812                              <1> ;;	..............................................................
  3813                              <1> ;;
  3814                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3815                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3816                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3817                              <1> ;;	position with value of 1 on the table is converted to swap
  3818                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3819                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3820                              <1> ;;	number of physical swap disk or virtual swap disk)
  3821                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3822                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3823                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3824                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3825                              <1> ;;	If disk write procedure returns with error or free count of 
  3826                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3827                              <1> ;;	'insufficient memory error' (cf=1). 
  3828                              <1> ;;
  3829                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3830                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3831                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3832                              <1> ;;	free blocks after a disk write error. It will return to 
  3833                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3834                              <1> ;;
  3835                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3836                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3837                              <1> ;;	address (cf=0). 
  3838                              <1> ;;
  3839                              <1> ;;	..............................................................
  3840                              <1> ;;
  3841                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3842                              <1> ;;	file sectors at specified memory page. Then page allocation
  3843                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3844                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3845                              <1> ;;	to do, except to terminate the process which is the owner of
  3846                              <1> ;;	the swapped page.
  3847                              <1> ;;
  3848                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3849                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3850                              <1> ;;	updates [swpd_first] pointer if it is required.
  3851                              <1> ;;
  3852                              <1> ;;	..............................................................	 
  3853                              <1> ;;
  3854                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3855                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3856                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3857                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3858                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3859                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3860                              <1> ;;
  3861                              <1> 
  3862                              <1> ; 24/12/2021
  3863                              <1> ; ('swap_in' procedure call is disabled)
  3864                              <1> 
  3865                              <1> ;swap_in:
  3866                              <1> 	; 31/08/2015
  3867                              <1> 	; 20/07/2015
  3868                              <1> 	; 28/04/2015
  3869                              <1> 	; 18/04/2015
  3870                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3871                              <1> 	;
  3872                              <1> 	; INPUT -> 
  3873                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3874                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3875                              <1> 	;	EAX = Offset Address for the swapped page on the
  3876                              <1> 	;	      swap disk or in the swap file.
  3877                              <1> 	;
  3878                              <1> 	; OUTPUT ->
  3879                              <1> 	;	EAX = 0 if loading at memory has been successful
  3880                              <1> 	;
  3881                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3882                              <1> 	;		  or sector not present or drive not ready
  3883                              <1> 	;	     EAX = Error code
  3884                              <1> 	;	     [u.error] = EAX 
  3885                              <1> 	;		       = The last error code for the process
  3886                              <1> 	;		         (will be reset after returning to user)	  
  3887                              <1> 	;
  3888                              <1> 	; Modified Registers -> EAX
  3889                              <1> 	;
  3890                              <1> 
  3891                              <1> ;       cmp     dword [swp_drv], 0
  3892                              <1> ;	jna	short swpin_dnp_err
  3893                              <1> ;
  3894                              <1> ;	cmp	eax, [swpd_size]
  3895                              <1> ;	jnb	short swpin_snp_err
  3896                              <1> ;
  3897                              <1> ;	push	esi
  3898                              <1> ;	push	ebx
  3899                              <1> ;	push	ecx
  3900                              <1> ;	mov	esi, [swp_drv]	
  3901                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3902                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3903                              <1> ;		; size different than 512 bytes, logical disk sector
  3904                              <1> ;		; size is 512 bytes and disk reading procedure
  3905                              <1> ;		; will be performed for reading 4096 bytes
  3906                              <1> ;		; (2*2048, 8*512). 
  3907                              <1> ;	; ESI = Logical disk description table address
  3908                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3909                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3910                              <1> ;	; ECX = Sector count ; 8 sectors
  3911                              <1> ;	push	eax
  3912                              <1> ;	call	logical_disk_read
  3913                              <1> ;	pop	eax
  3914                              <1> ;	jnc	short swpin_read_ok
  3915                              <1> ;	;
  3916                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3917                              <1> ;	mov	[u.error], eax
  3918                              <1> ;	jmp	short swpin_retn
  3919                              <1> ;	;
  3920                              <1> ;swpin_read_ok:
  3921                              <1> ;	; EAX = Offset address (logical sector number)
  3922                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3923                              <1> ;	;
  3924                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3925                              <1> ;	; 20/07/2015
  3926                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3927                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3928                              <1> ;	mov	bl, [u.uno] ; current process number
  3929                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3930                              <1> ;	call	swap_queue_shift
  3931                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3932                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3933                              <1> ;	; zf = 1
  3934                              <1> ;swpin_retn:
  3935                              <1> ;	pop	ecx
  3936                              <1> ;	pop	ebx
  3937                              <1> ;	pop	esi
  3938                              <1> ;	retn
  3939                              <1> ;
  3940                              <1> ;swpin_dnp_err:
  3941                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3942                              <1> ;swpin_err_retn:
  3943                              <1> ;	mov	[u.error], eax
  3944                              <1> ;	stc
  3945                              <1> ;	retn
  3946                              <1> ;
  3947                              <1> ;swpin_snp_err:
  3948                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3949                              <1> ;	jmp	short swpin_err_retn
  3950                              <1> 
  3951                              <1> ; 24/12/2021
  3952                              <1> ; ('swap_out' procedure call is disabled)
  3953                              <1> 
  3954                              <1> ;swap_out:
  3955                              <1> 	; 10/06/2016
  3956                              <1> 	; 07/06/2016
  3957                              <1>         ; 23/05/2016
  3958                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3959                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3960                              <1> 	;
  3961                              <1> 	; INPUT -> 
  3962                              <1> 	;	none
  3963                              <1> 	;
  3964                              <1> 	; OUTPUT ->
  3965                              <1> 	;	EAX = Physical page address (which is swapped out
  3966                              <1> 	;	      for allocating a new page)
  3967                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3968                              <1> 	;		  or sector not present or drive not ready
  3969                              <1> 	;	     EAX = Error code
  3970                              <1> 	;	     [u.error] = EAX 
  3971                              <1> 	;		       = The last error code for the process
  3972                              <1> 	;		         (will be reset after returning to user)	  
  3973                              <1> 	;
  3974                              <1> 	; Modified Registers -> none (except EAX)
  3975                              <1> 	;
  3976                              <1> 
  3977                              <1> ;	cmp 	word [swpq_count], 1
  3978                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3979                              <1> ;
  3980                              <1> ;       ;cmp    dword [swp_drv], 1
  3981                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3982                              <1> ;
  3983                              <1> ;       cmp     dword [swpd_free], 1
  3984                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3985                              <1> ;
  3986                              <1> ;	push	ebx ; *
  3987                              <1> ;swpout_1:
  3988                              <1> ;	; 10/06/2016
  3989                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3990                              <1> ;	call	swap_queue_shift
  3991                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3992                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3993                              <1> ;				       ; pointer in the swap queue
  3994                              <1> ;	; EAX = PTE value of the page
  3995                              <1> ;	; EBX = PTE address of the page
  3996                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3997                              <1> ;	;
  3998                              <1> ;	; 07/06/2016
  3999                              <1> ;	; 19/05/2016
  4000                              <1> ;	; check this page is in timer events or not
  4001                              <1> ;	
  4002                              <1> ;swpout_timer_page_0:
  4003                              <1> ;	push	edx ; **
  4004                              <1> ;
  4005                              <1> ;	; 07/06/2016
  4006                              <1> ;	cmp	byte [timer_events], 0 
  4007                              <1> ;	jna	short swpout_2
  4008                              <1> ;	;
  4009                              <1> ;	mov	dl, [timer_events]
  4010                              <1> ;
  4011                              <1> ;	push	ecx ; ***
  4012                              <1> ;	push	ebx ; ****
  4013                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  4014                              <1> ;			       ; structures 
  4015                              <1> ;swpout_timer_page_1:
  4016                              <1> ;	mov	cl, [ebx]
  4017                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  4018                              <1> ;	jz	short swpout_timer_page_3
  4019                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  4020                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  4021                              <1> ;				; of the response byte address, to
  4022                              <1> ;				; get beginning of the page address)
  4023                              <1> ;	cmp	eax, ecx
  4024                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  4025                              <1> ;	
  4026                              <1> ;	; !same page!
  4027                              <1> ;	;
  4028                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  4029                              <1> ;	; This page will be used by the kernel to put timer event
  4030                              <1> ;	; response (signal return) byte at the requested address;
  4031                              <1> ;	; in order to prevent a possible wrong write (while
  4032                              <1> ;	; this page is swapped out) on physical memory,
  4033                              <1> ;	; we must protect this page against to be swapped out!
  4034                              <1> ;	;
  4035                              <1> ;	pop	ebx ; ****
  4036                              <1> ;	pop	ecx ; ***
  4037                              <1> ;	pop	edx ; **
  4038                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  4039                              <1> ; 
  4040                              <1> ;swpout_timer_page_2:
  4041                              <1> ;	; 07/06/2016
  4042                              <1> ;	dec	dl
  4043                              <1> ;	jz	short swpout_timer_page_4
  4044                              <1> ;swpout_timer_page_3:
  4045                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  4046                              <1> ;	;jnb	short swpout_timer_page_4
  4047                              <1> ;	add	ebx, 16
  4048                              <1> ;	jmp	short swpout_timer_page_1	
  4049                              <1> ;
  4050                              <1> ;swpout_timer_page_4:
  4051                              <1> ;	pop	ebx ; ****
  4052                              <1> ;	pop	ecx ; ***
  4053                              <1> ;swpout_2:
  4054                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4055                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4056                              <1> ;	;
  4057                              <1> ;	call	link_swap_block
  4058                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4059                              <1> ;				       ; because [swpd_free] value
  4060                              <1> ;				       ; was checked at the beginging. 	
  4061                              <1> ;	pop	edx ; **
  4062                              <1> ;	pop	ebx ; *
  4063                              <1> ;	jmp	short swpout_nfspc_err 
  4064                              <1> ;swpout_3:
  4065                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4066                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4067                              <1> ;	;	
  4068                              <1> ;	push	esi ; **
  4069                              <1> ;	push	ecx ; ***
  4070                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4071                              <1> ;	mov	esi, [swp_drv]	
  4072                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4073                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4074                              <1> ;		; size different than 512 bytes, logical disk sector
  4075                              <1> ;		; size is 512 bytes and disk writing procedure
  4076                              <1> ;		; will be performed for writing 4096 bytes
  4077                              <1> ;		; (2*2048, 8*512). 
  4078                              <1> ;	; ESI = Logical disk description table address
  4079                              <1> ;	; EBX = Buffer (Page) address
  4080                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4081                              <1> ;	; ECX = Sector count ; 8 sectors
  4082                              <1> ;	; edx = PTE address
  4083                              <1> ;	call	logical_disk_write
  4084                              <1> ;	; edx = PTE address
  4085                              <1> ;	pop	ecx ; sector address	
  4086                              <1> ;	jnc	short swpout_write_ok
  4087                              <1> ;	;
  4088                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4089                              <1> ;swpout_dw_err:
  4090                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4091                              <1> ;	mov	[u.error], eax
  4092                              <1> ;	jmp	short swpout_retn
  4093                              <1> ;	;
  4094                              <1> ;swpout_write_ok:
  4095                              <1> ;	; EBX = Buffer (page) address
  4096                              <1> ;	; EDX = Page Table Entry address
  4097                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4098                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4099                              <1> ;	mov 	[edx], ecx 
  4100                              <1> ;		; bit 0 = 0 (swapped page)
  4101                              <1> ;	mov	eax, ebx
  4102                              <1> ;swpout_retn:
  4103                              <1> ;	pop	ecx ; ***
  4104                              <1> ;	pop	esi ; **
  4105                              <1> ;	pop	ebx ; *
  4106                              <1> ;	retn
  4107                              <1> ;
  4108                              <1> ;;swpout_dnp_err:
  4109                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4110                              <1> ;;	jmp	short swpout_err_retn
  4111                              <1> ;swpout_nfspc_err:
  4112                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4113                              <1> ;swpout_err_retn:
  4114                              <1> ;	mov	[u.error], eax
  4115                              <1> ;	;stc
  4116                              <1> ;	retn
  4117                              <1> ;swpout_npts_err:
  4118                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4119                              <1> ;	pop	ebx
  4120                              <1> ;	jmp	short swpout_err_retn
  4121                              <1> ;swpout_im_err:
  4122                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4123                              <1> ;	jmp	short swpout_err_retn
  4124                              <1> 
  4125                              <1> ; 24/12/2021
  4126                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4127                              <1> 
  4128                              <1> ;swap_queue_shift:
  4129                              <1> 	; 26/03/2017
  4130                              <1> 	; 10/06/2016
  4131                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4132                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4133                              <1> 	;
  4134                              <1> 	; INPUT ->
  4135                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4136                              <1> 	;	      and process number combination (bit 0 to 11)
  4137                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4138                              <1> 	;	
  4139                              <1> 	; OUTPUT ->
  4140                              <1> 	;	If EBX input > 0 
  4141                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4142                              <1> 	; 	   from the tail to the head, up to entry offset
  4143                              <1> 	; 	   which points to EBX input value or nothing
  4144                              <1> 	;	   to do if EBX value is not found on the queue.
  4145                              <1> 	;	   (The entry -with EBX value- will be removed
  4146                              <1> 	;	   from the queue if it is found.)
  4147                              <1> 	;
  4148                              <1> 	;	   EAX = 0		
  4149                              <1> 	;
  4150                              <1> 	;	If EBX input = 0
  4151                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4152                              <1> 	; 	   from the tail to the head, if the PTE address
  4153                              <1> 	;	   which is pointed in head of the queue is marked
  4154                              <1> 	;	   as "accessed" or it is marked as "non present".
  4155                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4156                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4157                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4158                              <1> 	;	   -without dropping pointer of the PTE from 
  4159                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4160                              <1> 	;	   Pointer in the head will be moved into the tail,
  4161                              <1> 	;	   other PTEs will be shifted on head direction.)
  4162                              <1> 	;
  4163                              <1> 	;	   Swap queue will be shifted up to the first
  4164                              <1> 	;	   'present' or 'non accessed' page will be found
  4165                              <1> 	;	   (as pointed) on the queue head (then it will be
  4166                              <1>         ;          removed/dropped from the queue).
  4167                              <1> 	;
  4168                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4169                              <1> 	;		 (it's pointer -virtual address-) dropped
  4170                              <1> 	;		 (removed) from swap queue.
  4171                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4172                              <1> 	;	         which is (it's pointer -virtual address-)
  4173                              <1> 	;		 dropped (removed) from swap queue.
  4174                              <1> 	;
  4175                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4176                              <1> 	;
  4177                              <1> 	; Modified Registers -> EAX, EBX
  4178                              <1> 	;
  4179                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4180                              <1> ;	and	ax, ax
  4181                              <1> ;	jz	short swpqs_retn
  4182                              <1> ;	push	edi
  4183                              <1> ;	push	esi
  4184                              <1> ;	push	ecx
  4185                              <1> ;	mov	esi, swap_queue
  4186                              <1> ;	mov	ecx, eax
  4187                              <1> ;	or	ebx, ebx
  4188                              <1> ;	jz	short swpqs_7
  4189                              <1> ;swpqs_1:
  4190                              <1> ;	lodsd
  4191                              <1> ;	cmp	eax, ebx
  4192                              <1> ;	je	short swpqs_2
  4193                              <1> ;	loop	swpqs_1
  4194                              <1> ;	; 10/06/2016
  4195                              <1> ;	sub	eax, eax 
  4196                              <1> ;	jmp	short swpqs_6
  4197                              <1> ;swpqs_2:
  4198                              <1> ;	mov	edi, esi
  4199                              <1> ;	sub 	edi, 4
  4200                              <1> ;swpqs_3:
  4201                              <1> ;	dec	word [swpq_count]
  4202                              <1> ;	jz	short swpqs_5
  4203                              <1> ;swpqs_4:
  4204                              <1> ;	dec 	ecx
  4205                              <1> ;	rep	movsd	; shift up (to the head)
  4206                              <1> ;swpqs_5:
  4207                              <1> ;	xor	eax, eax
  4208                              <1> ;	mov	[edi], eax
  4209                              <1> ;swpqs_6:
  4210                              <1> ;	pop	ecx
  4211                              <1> ;	pop	esi
  4212                              <1> ;	pop	edi
  4213                              <1> ;swpqs_retn:
  4214                              <1> ;	retn		
  4215                              <1> ;swpqs_7:
  4216                              <1> ;	mov	edi, esi ; head
  4217                              <1> ;	lodsd
  4218                              <1> ;	; 20/07/2015
  4219                              <1> ;	mov	ebx, eax
  4220                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4221                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4222                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4223                              <1> ;		      ; ax = process number (1 to 4095)
  4224                              <1> ;	cmp	al, [u.uno]
  4225                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4226                              <1> ;	jne	short swpqs_8
  4227                              <1> ;	mov	eax, [u.pgdir]
  4228                              <1> ;	jmp	short swpqs_9
  4229                              <1> ;swpqs_8:
  4230                              <1> ;	; 09/06/2016
  4231                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4232                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4233                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4234                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4235                              <1> ;
  4236                              <1> ;	;shl	ax, 2
  4237                              <1> ;	shl	al, 2
  4238                              <1> ;	mov 	eax, [eax+p.upage-4]
  4239                              <1> ;	or	eax, eax
  4240                              <1> ;	jz	short swpqs_3 ; invalid upage
  4241                              <1> ;	add	eax, u.pgdir - user
  4242                              <1> ;			 ; u.pgdir value for the process
  4243                              <1> ;			 ; is in [eax]
  4244                              <1> ;	mov	eax, [eax]
  4245                              <1> ;	and	eax, eax
  4246                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4247                              <1> ;swpqs_9:
  4248                              <1> ;	push	edx
  4249                              <1> ;	; eax = page directory
  4250                              <1> ;	; ebx = virtual address
  4251                              <1> ;	call	get_pte
  4252                              <1> ;	mov	ebx, edx	; PTE address
  4253                              <1> ;	pop	edx
  4254                              <1> ;	; 10/06/2016
  4255                              <1> ;	jc	short swpqs_13 ; empty PDE
  4256                              <1> ;	; EAX = PTE value
  4257                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4258                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4259                              <1> ;			        ; from the queue (head)
  4260                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4261                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4262                              <1> ;			        ; from the queue (head) 	
  4263                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4264                              <1> ;	;jnz	short swpqs_11  ; present
  4265                              <1> ;			        ; accessed page
  4266                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4267                              <1> ;	jc	short swpqs_11  ; accessed page
  4268                              <1> ;
  4269                              <1> ;	dec	ecx
  4270                              <1> ;	mov	[swpq_count], cx
  4271                              <1> ;       jz      short swpqs_10
  4272                              <1> ;		; esi = head + 4
  4273                              <1> ;		; edi = head
  4274                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4275                              <1> ;swpqs_10:
  4276                              <1> ;	mov	[edi], ecx ; 0
  4277                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4278                              <1> ;
  4279                              <1> ;swpqs_11:
  4280                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4281                              <1> ;	; Rotation (head -> tail)
  4282                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4283                              <1> ;	jz	short swpqs_10
  4284                              <1> ;		; esi = head + 4
  4285                              <1> ;		; edi = head
  4286                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4287                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4288                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4289                              <1> ;
  4290                              <1> ;	mov	cx, [swpq_count]
  4291                              <1> ;
  4292                              <1> ;swpqs_12:
  4293                              <1> ;	mov	esi, swap_queue ; head
  4294                              <1> ;       jmp     swpqs_7
  4295                              <1> ;
  4296                              <1> ;swpqs_13:
  4297                              <1> ;	dec	ecx
  4298                              <1> ;	mov	[swpq_count], cx
  4299                              <1> ;       jz      swpqs_5
  4300                              <1> ;	jmp	short swpqs_12
  4301                              <1> 
  4302                              <1> ; 24/12/2021
  4303                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4304                              <1> 
  4305                              <1> ;add_to_swap_queue:
  4306                              <1> 	; 20/02/2017
  4307                              <1> 	; 20/07/2015
  4308                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4309                              <1> 	;
  4310                              <1> 	; Adds new page to swap queue
  4311                              <1> 	; (page directories and page tables must not be added
  4312                              <1> 	; to swap queue)	
  4313                              <1> 	;
  4314                              <1> 	; INPUT ->
  4315                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4316                              <1> 	;	[u.uno]
  4317                              <1> 	;	20/02/2017
  4318                              <1> 	;	(Linear address = CORE + user's virtual address)
  4319                              <1> 	;
  4320                              <1> 	; OUTPUT ->
  4321                              <1> 	;	EAX = [swpq_count]
  4322                              <1> 	;	      (after the PTE has been added)
  4323                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4324                              <1> 	;	      the PTE could not be added.
  4325                              <1> 	;
  4326                              <1> 	; Modified Registers -> EAX
  4327                              <1> 	;
  4328                              <1> ;	push	ebx
  4329                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4330                              <1> ;	mov	bl, [u.uno] ; current process number
  4331                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4332                              <1> ;				 ; it is already on the queue
  4333                              <1> ;		; then add it to the tail of the queue
  4334                              <1> ;	movzx	eax, word [swpq_count]
  4335                              <1> ;	cmp	ax, 1024
  4336                              <1> ;	jb	short atsq_1
  4337                              <1> ;	sub	ax, ax
  4338                              <1> ;	pop	ebx
  4339                              <1> ;	retn
  4340                              <1> ;atsq_1:
  4341                              <1> ;	push	esi
  4342                              <1> ;	mov	esi, swap_queue
  4343                              <1> ;	and	ax, ax
  4344                              <1> ;	jz	short atsq_2
  4345                              <1> ;	shl	ax, 2	; convert to offset
  4346                              <1> ;	add	esi, eax
  4347                              <1> ;	shr	ax, 2
  4348                              <1> ;atsq_2:
  4349                              <1> ;	inc	ax
  4350                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4351                              <1> ;	mov	[swpq_count], ax
  4352                              <1> ;	pop	esi
  4353                              <1> ;	pop	ebx
  4354                              <1> ;	retn
  4355                              <1> 
  4356                              <1> ; 24/12/2021
  4357                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4358                              <1> 
  4359                              <1> ;unlink_swap_block:
  4360                              <1> 	; 15/09/2015
  4361                              <1> 	; 30/04/2015
  4362                              <1> 	; 18/04/2015
  4363                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4364                              <1> 	;
  4365                              <1> 	; INPUT -> 
  4366                              <1> 	;	EAX = swap disk/file offset address
  4367                              <1> 	;	      (bit 1 to bit 31)
  4368                              <1> 	; OUTPUT ->
  4369                              <1> 	;	[swpd_free] is increased
  4370                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4371                              <1> 	;
  4372                              <1> 	; Modified Registers -> EAX
  4373                              <1> 	;
  4374                              <1> ;	push	ebx
  4375                              <1> ;	push	edx
  4376                              <1> ;	;
  4377                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4378                              <1> ;				     ; 3 bits right
  4379                              <1> ;				     ; to get swap block/page number
  4380                              <1> ;	mov	edx, eax
  4381                              <1> ;	; 15/09/2015
  4382                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4383                              <1> ;				     ; (1 allocation bit = 1 page)
  4384                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4385                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4386                              <1> ;				     ; (to get 32 bit position)			
  4387                              <1> ;	;
  4388                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4389                              <1> ;	add	ebx, edx
  4390                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4391                              <1> ;				     ; (allocation bit position)	 
  4392                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4393                              <1> ;				     ; than the address in 'swpd_next' ?
  4394                              <1> ;				     ; (next/first free block value)		
  4395                              <1> ;	jnb	short uswpbl_1	     ; no	
  4396                              <1> ;	mov	[swpd_next], eax     ; yes	
  4397                              <1> ;uswpbl_1:
  4398                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4399                              <1> ;				     ; set relevant bit to 1.
  4400                              <1> ;				     ; set CF to the previous bit value	
  4401                              <1> ;	cmc			     ; complement carry flag	
  4402                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4403                              <1> ;				     ; if the block is already deallocated
  4404                              <1> ;				     ; before.	
  4405                              <1> ;       inc     dword [swpd_free]
  4406                              <1> ;uswpbl_2:
  4407                              <1> ;	pop	edx
  4408                              <1> ;	pop	ebx
  4409                              <1> ;	retn
  4410                              <1> 
  4411                              <1> ; 24/12/2021
  4412                              <1> ; ('link_swap_block' procedure call is disabled)
  4413                              <1> 
  4414                              <1> ;link_swap_block:
  4415                              <1> 	; 01/07/2015
  4416                              <1> 	; 18/04/2015
  4417                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4418                              <1> 	;
  4419                              <1> 	; INPUT -> none
  4420                              <1> 	;
  4421                              <1> 	; OUTPUT ->
  4422                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4423                              <1> 	;	      in sectors (corresponding 
  4424                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4425                              <1> 	;
  4426                              <1> 	;	CF = 1 and EAX = 0 
  4427                              <1> 	; 		   if there is not a free block to be allocated	
  4428                              <1> 	;
  4429                              <1> 	; Modified Registers -> none (except EAX)
  4430                              <1> 	;
  4431                              <1> 
  4432                              <1> ;	;mov	eax, [swpd_free]
  4433                              <1> ;	;and	eax, eax
  4434                              <1> ;	;jz	short out_of_swpspc
  4435                              <1> ;	;
  4436                              <1> ;	push	ebx
  4437                              <1> ;	push	ecx
  4438                              <1> ;	;
  4439                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4440                              <1> ;	mov	ecx, ebx
  4441                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4442                              <1> ;				 ; next_free_swap_block >> 5
  4443                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4444                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4445                              <1> ;lswbl_scan:
  4446                              <1> ;	cmp	ebx, ecx
  4447                              <1> ;	ja	short lswbl_notfound
  4448                              <1> ;	;
  4449                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4450                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4451                              <1> ;			   ; loads the destination with an index to
  4452                              <1> ;			   ; first set bit. (0 -> 31) 
  4453                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4454                              <1> ;	; 01/07/2015
  4455                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4456                              <1> ;			 ;
  4457                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4458                              <1> ;			 ;	  with value of 1 means 
  4459                              <1> ;			 ;	  the corresponding page is free 
  4460                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4461                              <1> ;	add	ebx, 4
  4462                              <1> ;			 ; We return back for searching next page block
  4463                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4464                              <1> ;			 ;	 we always will find at least 1 free block here.
  4465                              <1> ;	jmp    	short lswbl_scan
  4466                              <1> ;	;
  4467                              <1> ;lswbl_notfound:	
  4468                              <1> ;	sub	ecx, swap_alloc_table
  4469                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4470                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4471                              <1> ;	xor	eax, eax
  4472                              <1> ;	mov	[swpd_free], eax
  4473                              <1> ;	stc
  4474                              <1> ;lswbl_ok:
  4475                              <1> ;	pop	ecx
  4476                              <1> ;	pop	ebx
  4477                              <1> ;	retn
  4478                              <1> ;	;
  4479                              <1> ;;out_of_swpspc:
  4480                              <1> ;;	stc
  4481                              <1> ;;	retn
  4482                              <1> ;
  4483                              <1> ;lswbl_found:
  4484                              <1> ;	mov	ecx, ebx
  4485                              <1> ;	sub	ecx, swap_alloc_table
  4486                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4487                              <1> ;				 ; address/offset (to the next)
  4488                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4489                              <1> ;	;
  4490                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4491                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4492                              <1> ;				 ; in the destination.
  4493                              <1> ;				 ;
  4494                              <1> ;				 ; Reset the bit which is corresponding to the 
  4495                              <1> ;				 ; (just) allocated block.
  4496                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4497                              <1> ;	add	eax, ecx	 ; = block number
  4498                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4499                              <1> ;				 ; 1 block =  8 sectors
  4500                              <1> ;	;
  4501                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4502                              <1> ;	;
  4503                              <1> ;	; NOTE: The relevant page table entry will be updated
  4504                              <1> ;	;       according to this EAX value...
  4505                              <1> ;	;
  4506                              <1> ;	jmp	short lswbl_ok
  4507                              <1> 
  4508                              <1> ; 24/12/2021
  4509                              <1> ; ('logical_disk_read' procedure call is disabled)
  4510                              <1> 
  4511                              <1> ;logical_disk_read:
  4512                              <1> 	; 20/07/2015
  4513                              <1> 	; 09/03/2015 (temporary code here)
  4514                              <1> 	;
  4515                              <1> 	; INPUT ->
  4516                              <1> 	; 	ESI = Logical disk description table address
  4517                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4518                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4519                              <1> 	; 	ECX = Sector count
  4520                              <1> 	;
  4521                              <1> 	;
  4522                              <1> ;	retn
  4523                              <1> 
  4524                              <1> ; 24/12/2021
  4525                              <1> ; ('logical_disk_write' procedure call is disabled)
  4526                              <1> 
  4527                              <1> ;logical_disk_write:
  4528                              <1> 	; 20/07/2015
  4529                              <1> 	; 09/03/2015 (temporary code here)
  4530                              <1> 	;
  4531                              <1> 	; INPUT ->
  4532                              <1> 	; 	ESI = Logical disk description table address
  4533                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4534                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4535                              <1> 	; 	ECX = Sector count
  4536                              <1> 	;
  4537                              <1> ;	retn
  4538                              <1> 
  4539                              <1> get_physical_addr:
  4540                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4541                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4542                              <1> 	; 18/10/2015
  4543                              <1> 	; 29/07/2015
  4544                              <1> 	; 20/07/2015
  4545                              <1> 	; 04/06/2015
  4546                              <1> 	; 20/05/2015
  4547                              <1> 	; 28/04/2015
  4548                              <1> 	; 18/04/2015
  4549                              <1> 	; Get physical address
  4550                              <1> 	;     (allocates a new page for user if it is not present)
  4551                              <1> 	;	
  4552                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4553                              <1> 	; (buffer) address to physical address (of the buffer).)
  4554                              <1> 	; ('sys write', 'sys read' system calls...)
  4555                              <1> 	;
  4556                              <1> 	; INPUT ->
  4557                              <1> 	;	EBX = virtual address
  4558                              <1> 	;	u.pgdir = page directory (physical) address
  4559                              <1> 	;
  4560                              <1> 	; OUTPUT ->
  4561                              <1> 	;	EAX = physical address 
  4562                              <1> 	;	EBX = linear address	
  4563                              <1> 	;	EDX = physical address of the page frame
  4564                              <1> 	;	      (with attribute bits)
  4565                              <1> 	;	ECX = byte count within the page frame
  4566                              <1> 	;
  4567                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4568                              <1> 	;
  4569                              <1> 
  4570                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4571 000031A2 A1[A56F0000]        <1> 	mov	eax, [u.pgdir]
  4572                              <1> 
  4573                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4574                              <1> 	
  4575 000031A7 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4576                              <1> 	;
  4577                              <1> 	;mov	eax, [u.pgdir]
  4578 000031AD E816FDFFFF          <1> 	call	get_pte
  4579                              <1> 		; EDX = Page table entry address (if CF=0)
  4580                              <1> 	        ;       Page directory entry address (if CF=1)
  4581                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4582                              <1> 		; EAX = Page table entry value (page address)
  4583                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4584 000031B2 731C                <1> 	jnc	short gpa_1
  4585                              <1> 	;
  4586 000031B4 E8FDFBFFFF          <1> 	call	allocate_page
  4587 000031B9 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4588                              <1> gpa_0:
  4589 000031BB E867FCFFFF          <1> 	call 	clear_page
  4590                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4591 000031C0 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4592                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4593                              <1> 			   ; (user, writable, present page)	
  4594 000031C2 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4595 000031C4 A1[A56F0000]        <1> 	mov	eax, [u.pgdir]	
  4596 000031C9 E8FAFCFFFF          <1> 	call	get_pte
  4597 000031CE 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4598                              <1> gpa_1:
  4599                              <1> 	; EAX = PTE value, EDX = PTE address
  4600 000031D0 A801                <1> 	test 	al, PTE_A_PRESENT
  4601 000031D2 750A                <1> 	jnz	short gpa_3
  4602 000031D4 09C0                <1> 	or	eax, eax
  4603 000031D6 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4604                              <1> 
  4605                              <1> ; 24/12/2021
  4606                              <1> ; ('reload_page' procedure call is disabled)
  4607 000031D8 EB2C                <1> 	jmp	short gpa_im_err
  4608                              <1> 
  4609                              <1> 	; 20/07/2015
  4610                              <1> ;	push	ebp
  4611                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4612                              <1> ;	; reload swapped page
  4613                              <1> ;	call	reload_page ; 28/04/2015
  4614                              <1> ;	pop	ebp
  4615                              <1> ;	jc	short gpa_retn
  4616                              <1> gpa_2:
  4617                              <1> ; 24/12/2021
  4618                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4619                              <1> 
  4620                              <1> 	; 20/07/2015
  4621                              <1> 	; 20/05/2015
  4622                              <1> 	; add this page to swap queue
  4623                              <1> ;	push	eax 
  4624                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4625                              <1> ;	call 	add_to_swap_queue
  4626                              <1> ;	pop	eax
  4627                              <1> 		; PTE address in EDX
  4628                              <1> 		; virtual address in EBX
  4629                              <1> 	; EAX = memory page address
  4630 000031DA 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4631                              <1> 				  ; present flag, bit 0 = 1
  4632                              <1> 				  ; user flag, bit 2 = 1	
  4633                              <1> 				  ; writable flag, bit 1 = 1
  4634 000031DC 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4635                              <1> gpa_3:
  4636                              <1> 	; 18/10/2015
  4637 000031DE 89D9                <1> 	mov	ecx, ebx
  4638 000031E0 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4639 000031E6 89C2                <1> 	mov 	edx, eax
  4640 000031E8 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4641 000031EC 01C8                <1> 	add	eax, ecx
  4642 000031EE F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4643 000031F0 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4644 000031F6 F8                  <1> 	clc
  4645                              <1> gpa_retn:
  4646 000031F7 C3                  <1> 	retn	
  4647                              <1> gpa_4:	
  4648 000031F8 E8B9FBFFFF          <1> 	call	allocate_page
  4649 000031FD 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4650 000031FF E823FCFFFF          <1> 	call	clear_page
  4651 00003204 EBD4                <1> 	jmp	short gpa_2
  4652                              <1> 
  4653                              <1> gpa_im_err:	
  4654 00003206 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4655                              <1> 				  ; Major error = 0 (No protection fault)	
  4656 0000320B C3                  <1> 	retn
  4657                              <1> 
  4658                              <1> ; 24/12/2021
  4659                              <1> ; ('reload_page' procedure call is disabled)
  4660                              <1> 
  4661                              <1> ;reload_page:
  4662                              <1> 	; 20/07/2015
  4663                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4664                              <1> 	;
  4665                              <1> 	; Reload (Restore) swapped page at memory
  4666                              <1> 	;
  4667                              <1> 	; INPUT -> 
  4668                              <1> 	;	EBP = Virtual (linear) memory address
  4669                              <1> 	;	EAX = PTE value (swap disk sector address)
  4670                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4671                              <1> 	; OUTPUT ->
  4672                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4673                              <1> 	;
  4674                              <1> 	;	CF = 1 and EAX = error code
  4675                              <1> 	;
  4676                              <1> 	; Modified Registers -> none (except EAX)
  4677                              <1> 	;
  4678                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4679                              <1> ;	push	ebx      ;
  4680                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4681                              <1> ;	call	allocate_page
  4682                              <1> ;	jc	short rlp_im_err
  4683                              <1> ;	xchg 	eax, ebx	
  4684                              <1> ;	; EBX = Physical memory (page) address
  4685                              <1> ;	; EAX = Swap disk (offset) address
  4686                              <1> ;	; EBP = Virtual (linear) memory address
  4687                              <1> ;	call	swap_in
  4688                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4689                              <1> ;	mov	eax, ebx	
  4690                              <1> ;rlp_retn:
  4691                              <1> ;	pop	ebx
  4692                              <1> ;	retn
  4693                              <1> ;	
  4694                              <1> ;rlp_im_err:	
  4695                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4696                              <1> ;				  ; Major error = 0 (No protection fault)	
  4697                              <1> ;	jmp	short rlp_retn
  4698                              <1> ;
  4699                              <1> ;rlp_swp_err:
  4700                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4701                              <1> ;	jmp	short rlp_retn
  4702                              <1> 
  4703                              <1> copy_page_dir:
  4704                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4705                              <1> 	; 19/09/2015
  4706                              <1> 	; temporary - 07/09/2015
  4707                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4708                              <1> 	;
  4709                              <1> 	; INPUT -> 
  4710                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4711                              <1> 	;		    page directory.
  4712                              <1> 	; OUTPUT ->
  4713                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4714                              <1> 	;	       page directory.
  4715                              <1> 	;	(New page directory with new page table entries.)
  4716                              <1> 	;	(New page tables with read only copies of the parent's
  4717                              <1> 	;	pages.)
  4718                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4719                              <1> 	;
  4720                              <1> 	; Modified Registers -> none (except EAX)
  4721                              <1> 	;
  4722 0000320C E8A5FBFFFF          <1> 	call	allocate_page
  4723 00003211 723E                <1> 	jc	short cpd_err
  4724                              <1> 	;
  4725 00003213 55                  <1> 	push	ebp ; 20/07/2015
  4726 00003214 56                  <1> 	push	esi
  4727 00003215 57                  <1> 	push	edi
  4728 00003216 53                  <1> 	push	ebx
  4729 00003217 51                  <1> 	push	ecx
  4730 00003218 8B35[A56F0000]      <1> 	mov	esi, [u.pgdir]
  4731 0000321E 89C7                <1> 	mov	edi, eax
  4732 00003220 50                  <1> 	push	eax ; save child's page directory address
  4733                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4734                              <1> 	; (use same system space for all user page tables) 
  4735 00003221 A5                  <1> 	movsd
  4736 00003222 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4737 00003227 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4738                              <1> cpd_0:	
  4739 0000322C AD                  <1> 	lodsd
  4740                              <1> 	;or	eax, eax
  4741                              <1>         ;jnz	short cpd_1
  4742 0000322D A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4743 0000322F 7508                <1> 	jnz	short cpd_1
  4744                              <1>  	; (virtual address at the end of the page table)	
  4745 00003231 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4746 00003237 EB0F                <1> 	jmp	short cpd_2
  4747                              <1> cpd_1:	
  4748 00003239 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4749 0000323D 89C3                <1> 	mov	ebx, eax
  4750                              <1> 	; EBX = Parent's page table address
  4751 0000323F E81F000000          <1> 	call	copy_page_table
  4752 00003244 720C                <1> 	jc	short cpd_p_err
  4753                              <1> 	; EAX = Child's page table address
  4754 00003246 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4755                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4756                              <1> 			 ; (present, writable, user)
  4757                              <1> cpd_2:
  4758 00003248 AB                  <1> 	stosd
  4759 00003249 E2E1                <1> 	loop	cpd_0
  4760                              <1> 	;
  4761 0000324B 58                  <1> 	pop	eax  ; restore child's page directory address
  4762                              <1> cpd_3:
  4763 0000324C 59                  <1> 	pop	ecx
  4764 0000324D 5B                  <1> 	pop	ebx
  4765 0000324E 5F                  <1> 	pop	edi
  4766 0000324F 5E                  <1> 	pop	esi
  4767 00003250 5D                  <1> 	pop	ebp
  4768                              <1> cpd_err:
  4769 00003251 C3                  <1> 	retn
  4770                              <1> cpd_p_err:
  4771                              <1> 	; release the allocated pages missing (recover free space)
  4772 00003252 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4773 00003253 8B1D[A56F0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4774 00003259 E888FCFFFF          <1> 	call 	deallocate_page_dir
  4775 0000325E 29C0                <1> 	sub	eax, eax ; 0
  4776 00003260 F9                  <1> 	stc
  4777 00003261 EBE9                <1> 	jmp	short cpd_3	
  4778                              <1> 
  4779                              <1> copy_page_table:
  4780                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4781                              <1> 	; 19/09/2015
  4782                              <1> 	; temporary - 07/09/2015
  4783                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4784                              <1> 	;
  4785                              <1> 	; INPUT -> 
  4786                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4787                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4788                              <1> 	; OUTPUT ->
  4789                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4790                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4791                              <1> 	;	CF = 1 -> error 
  4792                              <1> 	;
  4793                              <1> 	; Modified Registers -> EBP (except EAX)
  4794                              <1> 	;
  4795 00003263 E84EFBFFFF          <1> 	call	allocate_page
  4796 00003268 7244                <1> 	jc	short cpt_err
  4797                              <1> 	;
  4798 0000326A 50                  <1> 	push	eax ; *
  4799                              <1> 	;push 	ebx
  4800 0000326B 56                  <1> 	push	esi
  4801 0000326C 57                  <1> 	push	edi
  4802 0000326D 52                  <1> 	push	edx
  4803 0000326E 51                  <1> 	push	ecx
  4804                              <1> 	;
  4805 0000326F 89DE                <1> 	mov	esi, ebx
  4806 00003271 89C7                <1> 	mov	edi, eax
  4807 00003273 89C2                <1> 	mov	edx, eax
  4808 00003275 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4809                              <1> cpt_0:
  4810 0000327B AD                  <1> 	lodsd
  4811 0000327C A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4812                              <1> 	;jnz	short cpt_1 (*)
  4813                              <1> 	; 24/12/2021
  4814                              <1> 	;and	eax, eax (*)
  4815 0000327E 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4816                              <1> 	
  4817                              <1> ; 24/12/2021
  4818                              <1> ; ('reload_page' procedure call is disabled)
  4819                              <1> ;
  4820                              <1> ;	; ebp = virtual (linear) address of the memory page
  4821                              <1> ;	call	reload_page ; 28/04/2015
  4822                              <1> ;	jc	short cpt_p_err
  4823                              <1> cpt_1:
  4824 00003280 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4825 00003284 89C1                <1> 	mov	ecx, eax
  4826                              <1> 	; Allocate a new page for the child process
  4827 00003286 E82BFBFFFF          <1> 	call	allocate_page
  4828 0000328B 721C                <1> 	jc	short cpt_p_err
  4829 0000328D 57                  <1> 	push	edi
  4830 0000328E 56                  <1> 	push	esi
  4831 0000328F 89CE                <1> 	mov	esi, ecx
  4832 00003291 89C7                <1> 	mov	edi, eax
  4833 00003293 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4834 00003298 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4835 0000329A 5E                  <1> 	pop	esi
  4836 0000329B 5F                  <1> 	pop	edi
  4837                              <1> 	; 
  4838                              <1> ; 24/12/2021
  4839                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4840                              <1> ;
  4841                              <1> ;	push	ebx
  4842                              <1> ;	push	eax
  4843                              <1> ;	mov	ebx, ebp
  4844                              <1> ;	; ebx = virtual address of the memory page
  4845                              <1> ;	call	add_to_swap_queue
  4846                              <1> ;	pop	eax
  4847                              <1> ;	pop	ebx
  4848                              <1> 	;
  4849                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4850 0000329C 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4851                              <1> cpt_2:
  4852 0000329E AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4853                              <1> 	;
  4854 0000329F 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4855                              <1> 	;
  4856 000032A5 39D7                <1> 	cmp	edi, edx
  4857 000032A7 72D2                <1> 	jb	short cpt_0
  4858                              <1> cpt_p_err:
  4859 000032A9 59                  <1> 	pop	ecx
  4860 000032AA 5A                  <1> 	pop	edx
  4861 000032AB 5F                  <1> 	pop	edi
  4862 000032AC 5E                  <1> 	pop	esi
  4863                              <1> 	;pop	ebx
  4864 000032AD 58                  <1> 	pop	eax ; *
  4865                              <1> cpt_err:
  4866 000032AE C3                  <1> 	retn
  4867                              <1> 
  4868                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4869                              <1> 
  4870                              <1> ;; Data:
  4871                              <1> 
  4872                              <1> ; 09/03/2015
  4873                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4874                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4875                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4876                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4877                              <1> ;swpd_next:  dd 0 ; next free page block
  4878                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  2098                                  %include 'sysdefs.inc' ; 09/03/2015
  2099                              <1> ; Retro UNIX 386 v1.1 Kernel - SYSDEFS.INC
  2100                              <1> ; Last Modification: 08/02//2022
  2101                              <1> ;
  2102                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2103                              <1> ; (Modified from 
  2104                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2105                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2106                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2107                              <1> ; ----------------------------------------------------------------------------
  2108                              <1> ;
  2109                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2110                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2111                              <1> ; <Bell Laboratories (17/3/1972)>
  2112                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2113                              <1> ;
  2114                              <1> ; ****************************************************************************
  2115                              <1> 
  2116                              <1> nproc 	equ	16  ; number of processes
  2117                              <1> nfiles 	equ	50
  2118                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2119                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2120                              <1> 
  2121                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2122                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2123                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2124                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2125                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2126                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2127                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2128                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2129                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2130                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2131                              <1> 	; '/core' dump file size = 32768 bytes
  2132                              <1>  
  2133                              <1> ; 08/03/2014 
  2134                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2135                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2136                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2137                              <1> 
  2138                              <1> ; 30/08/2013
  2139                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2140                              <1> 
  2141                              <1> ; 05/02/2014
  2142                              <1> ; process status
  2143                              <1> ;SFREE 	equ 0
  2144                              <1> ;SRUN	equ 1
  2145                              <1> ;SWAIT	equ 2
  2146                              <1> ;SZOMB	equ 3
  2147                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2148                              <1> 
  2149                              <1> ; 09/03/2015
  2150                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2151                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2152                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2153                              <1> 
  2154                              <1> ; 17/09/2015
  2155                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2156                              <1> 
  2157                              <1> ; 21/09/2015 (36) 
  2158                              <1> ; 01/07/2015 (35)
  2159                              <1> ; 14/07/2013 (0-34)
  2160                              <1> ; UNIX v1 system calls
  2161                              <1> _rele 	equ 0
  2162                              <1> _exit 	equ 1
  2163                              <1> _fork 	equ 2
  2164                              <1> _read 	equ 3
  2165                              <1> _write	equ 4
  2166                              <1> _open	equ 5
  2167                              <1> _close 	equ 6
  2168                              <1> _wait 	equ 7
  2169                              <1> _creat 	equ 8
  2170                              <1> _link 	equ 9
  2171                              <1> _unlink	equ 10
  2172                              <1> _exec	equ 11
  2173                              <1> _chdir	equ 12
  2174                              <1> _time 	equ 13
  2175                              <1> _mkdir 	equ 14
  2176                              <1> _chmod	equ 15
  2177                              <1> _chown	equ 16
  2178                              <1> _break	equ 17
  2179                              <1> _stat	equ 18
  2180                              <1> _seek	equ 19
  2181                              <1> _tell 	equ 20
  2182                              <1> _mount	equ 21
  2183                              <1> _umount	equ 22
  2184                              <1> _setuid	equ 23
  2185                              <1> _getuid	equ 24
  2186                              <1> _stime	equ 25
  2187                              <1> _quit	equ 26	
  2188                              <1> _intr	equ 27
  2189                              <1> _fstat	equ 28
  2190                              <1> _emt 	equ 29
  2191                              <1> _mdate 	equ 30
  2192                              <1> _stty 	equ 31
  2193                              <1> _gtty	equ 32
  2194                              <1> _ilgins	equ 33
  2195                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2196                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2197                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2198                              <1> 
  2199                              <1> %macro sys 1-4
  2200                              <1>     ; 13/04/2015
  2201                              <1>     ; Retro UNIX 386 v1 system call.		
  2202                              <1>     mov eax, %1
  2203                              <1>     %if %0 >= 2   
  2204                              <1>         mov ebx, %2
  2205                              <1>         %if %0 >= 3    
  2206                              <1>             mov ecx, %3
  2207                              <1>             %if %0 = 4
  2208                              <1>                mov edx, %4   
  2209                              <1>             %endif
  2210                              <1>         %endif
  2211                              <1>     %endif
  2212                              <1>     int 30h	   
  2213                              <1> %endmacro
  2214                              <1> 
  2215                              <1> ; 13/05/2015 - ERROR CODES
  2216                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2217                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2218                              <1> ; 14/05/2015
  2219                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2220                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2221                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2222                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2223                              <1> ; 16/05/2015		
  2224                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2225                              <1> ; 18/05/2015
  2226                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2227                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2228                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2229                              <1> ; 07/06/2015
  2230                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2231                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2232                              <1> ; 09/06/2015
  2233                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2234                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2235                              <1> ; 16/06/2015
  2236                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2237                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2238                              <1> ; 22/06/2015
  2239                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2240                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2241                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2242                              <1> ; 23/06/2015
  2243                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2244                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2245                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2246                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2247                              <1> ; 27/06/2015
  2248                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2249                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2250                              <1> ; 29/06/2015
  2251                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2252                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2253                              <1> ; 08/02/2022 
  2254                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2255                              <1> ; 10/10/2016
  2256                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2257                              <1> ; 18/05/2016
  2258                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2259                              <1> ; 15/10/2016
  2260                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2261                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2262                              <1> ; 16/10/2016
  2263                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2264                              <1> ; 08/02/2022
  2265                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2266                              <1> 
  2267                              <1> ; 26/08/2015
  2268                              <1> ; 24/07/2015
  2269                              <1> ; 24/06/2015
  2270                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2271                              <1> ; 01/07/2015
  2272                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2273                              <1> ; 24/12/2021
  2274                              <1> ERR_INV_FUNC	   equ 1  ; 'invalid system call !' error	 					 		
  2099                                  %include 'u0.s'        ; 15/03/2015
  2100                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYS0.INC
  2101                              <1> ; Last Modification: 02/06/2022
  2102                              <1> ; ----------------------------------------------------------------------------
  2103                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2104                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2105                              <1> ;
  2106                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2107                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2108                              <1> ; <Bell Laboratories (17/3/1972)>
  2109                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2110                              <1> ;
  2111                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2112                              <1> ;
  2113                              <1> ; ****************************************************************************
  2114                              <1> 
  2115                              <1> sys_init:
  2116                              <1> 	; 26/02/2022
  2117                              <1> 	; 08/01/2022
  2118                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2119                              <1> 	; 18/10/2015
  2120                              <1> 	; 28/08/2015
  2121                              <1> 	; 24/08/2015
  2122                              <1> 	; 14/08/2015
  2123                              <1> 	; 24/07/2015 
  2124                              <1> 	; 02/07/2015
  2125                              <1> 	; 01/07/2015
  2126                              <1> 	; 23/06/2015
  2127                              <1> 	; 15/04/2015
  2128                              <1> 	; 13/03/2015
  2129                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2130                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2131                              <1> 	;
  2132                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2133                              <1> 	;
  2134                              <1> 	; 14/02/2014
  2135                              <1> 	; 14/07/2013
  2136                              <1> 	;;mov	ax, 41
  2137                              <1> 	; 24/12/2021
  2138                              <1> 	;xor	eax, eax
  2139                              <1> 	;mov	al, 41
  2140                              <1> 	;mov	[rootdir], ax
  2141                              <1> 	;mov	[u.cdir], ax
  2142                              <1> 	;;and	al, 1 ; 15/04/2015
  2143                              <1> 	;inc	al  ; ax = 1
  2144 000032AF B001                <1> 	mov	al, 1
  2145 000032B1 A2[9B6F0000]        <1> 	mov	[u.uno], al
  2146                              <1> 	;mov	[mpid], ax
  2147                              <1> 	;mov	[p.pid], ax
  2148 000032B6 A2[386F0000]        <1> 	mov	[mpid], al
  2149 000032BB A2[686C0000]        <1> 	mov	[p.pid], al	
  2150 000032C0 A2[C86C0000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2151                              <1> 	; 24/12/2021
  2152 000032C5 B029                <1> 	mov	al, 41
  2153                              <1> 	;mov	[rootdir], ax
  2154                              <1> 	;mov	[u.cdir], ax
  2155 000032C7 A2[3A6F0000]        <1> 	mov	[rootdir], al
  2156 000032CC A2[506F0000]        <1> 	mov	[u.cdir], al
  2157                              <1> 	;
  2158 000032D1 B004                <1> 	mov	al, time_count ; 30/08/2013
  2159 000032D3 A2[8E6F0000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2160                              <1> 	; 02/07/2015
  2161 000032D8 A1[886B0000]        <1> 	mov	eax, [k_page_dir]
  2162                              <1> 	;sub	eax, eax
  2163 000032DD A3[A56F0000]        <1> 	mov	[u.pgdir], eax ; reset
  2164                              <1> 	; 18/10/2015
  2165                              <1> 	;mov	[u.ppgdir], eax ; 0
  2166                              <1> 	; 26/02/2022
  2167                              <1>  	;call	epoch
  2168                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2169                              <1> 	; 17/07/2013
  2170 000032E2 E884060000          <1> 	call 	bf_init ; buffer initialization
  2171                              <1> 	; 26/02/2022
  2172                              <1> 	; (save sysinit time on sb0)
  2173 000032E7 E829030000          <1> 	call	epoch
  2174 000032EC A3[987D0000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2175                              <1> 	; 23/06/2015
  2176 000032F1 E8C0FAFFFF          <1> 	call	allocate_page
  2177                              <1> 	;;jc	error
  2178                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2179                              <1> 	; 24/12/2021
  2180 000032F6 7305                <1> 	jnc	short sysinit_1
  2181 000032F8 E989000000          <1> 	jmp	panic
  2182                              <1> sysinit_1:
  2183 000032FD A3[9C6F0000]        <1> 	mov	[u.upage], eax ; user structure page	
  2184 00003302 A3[D86C0000]        <1> 	mov	[p.upage], eax
  2185                              <1> 	;
  2186 00003307 E81BFBFFFF          <1> 	call	clear_page
  2187                              <1> 	;
  2188                              <1> 	; 14/08/2015
  2189 0000330C FA                  <1> 	cli
  2190                              <1> 	; 14/03/2015
  2191                              <1> 	; 17/01/2014
  2192 0000330D E8D0010000          <1> 	call	sp_init ; serial port initialization
  2193                              <1> 	; 14/08/2015
  2194 00003312 FB                  <1> 	sti
  2195                              <1> 	;
  2196                              <1> 	; 30/06/2015
  2197                              <1> 	;mov	esi, kernel_init_ok_msg
  2198                              <1> 	;call 	print_msg
  2199                              <1> 	;
  2200 00003313 30DB                <1> 	xor	bl, bl ; video page 0
  2201                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2202 00003315 E8450F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2203 0000331A FEC3                <1> 	inc	bl
  2204 0000331C 80FB08              <1> 	cmp	bl, 8
  2205 0000331F 72F4                <1> 	jb	short vp_clr_nxt
  2206                              <1> 	;
  2207                              <1> 	; 24/07/2015
  2208                              <1> 	;push    KDATA
  2209                              <1>         ;push    esp
  2210                              <1> 	;mov	[tss.esp0], esp
  2211                              <1>         ;mov     word [tss.ss0], KDATA
  2212                              <1> 	;
  2213                              <1> 	; 08/01/2022
  2214                              <1> 	; 24/08/2015
  2215                              <1> 	;; temporary (01/07/2015)
  2216                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2217                              <1> 			       ; it is not needed here !
  2218                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2219 00003321 FE0D[416F0000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2220                              <1> 			      ; 0 = executing a system call
  2221                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2222                              <1> 	;
  2223                              <1> 	;;; 06/08/2015
  2224                              <1> 	;;;call	getch ; wait for a key stroke
  2225                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2226                              <1> ;;sys_init_msg_wait:
  2227                              <1> ;;	push 	ecx
  2228                              <1> ;;	mov	al, 1
  2229                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2230                              <1> ;;	call	getc_n
  2231                              <1> ;;	pop	ecx
  2232                              <1> ;;	jnz	short sys_init_msg_ok
  2233                              <1> ;;	loop	sys_init_msg_wait
  2234                              <1> 	;
  2235                              <1> ;;sys_init_msg_ok:
  2236                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2237 00003327 6A10                <1> 	push	KDATA ; ss
  2238 00003329 54                  <1> 	push	esp
  2239 0000332A 9C                  <1> 	pushfd
  2240 0000332B 6A08                <1> 	push	KCODE ; cs
  2241 0000332D 68[5A330000]        <1> 	push	init_exec ; eip
  2242 00003332 8925[446F0000]      <1> 	mov	[u.sp], esp
  2243 00003338 1E                  <1> 	push	ds
  2244 00003339 06                  <1> 	push	es
  2245 0000333A 0FA0                <1> 	push	fs
  2246 0000333C 0FA8                <1> 	push	gs	
  2247 0000333E 60                  <1> 	pushad
  2248 0000333F 8925[486F0000]      <1> 	mov	[u.usp], esp
  2249 00003345 E8B11B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2250                              <1> 		      ; and interrupt return components (for IRET)
  2251 0000334A 61                  <1> 	popad
  2252 0000334B 6658                <1> 	pop	ax ; gs
  2253 0000334D 6658                <1> 	pop	ax ; fs
  2254 0000334F 6658                <1> 	pop	ax ; es
  2255 00003351 6658                <1> 	pop	ax ; ds	
  2256 00003353 58                  <1> 	pop	eax ; eip (init_exec)
  2257 00003354 6658                <1> 	pop	ax ; cs (KCODE)
  2258 00003356 58                  <1> 	pop	eax ; E-FLAGS
  2259 00003357 58                  <1> 	pop	eax ; esp
  2260 00003358 6658                <1> 	pop	ax ; ss (KDATA)
  2261                              <1> 	;
  2262                              <1> 	; 08/01/2022 ([u.ppgdir] is zero already)
  2263                              <1> 	;xor	eax, eax ; 0
  2264                              <1> 	;mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2265                              <1> 	;
  2266                              <1> 	; 02/07/2015
  2267                              <1> 	; [u.pgdir ] = [k_page_dir]
  2268                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2269                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2270                              <1> init_exec:
  2271                              <1> 	; 13/03/2013
  2272                              <1> 	; 24/07/2013
  2273 0000335A BB[7C330000]        <1> 	mov	ebx, init_file
  2274 0000335F B9[74330000]        <1> 	mov	ecx, init_argp
  2275                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2276                              <1> 	; ECX contains address of argument list pointer
  2277                              <1> 	;
  2278                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2279                              <1> 			      ; 0 = executing a system call
  2280                              <1> 	sys	_exec  ; execute file
  2200                              <2> 
  2201                              <2> 
  2202 00003364 B80B000000          <2>  mov eax, %1
  2203                              <2>  %if %0 >= 2
  2204                              <2>  mov ebx, %2
  2205                              <2>  %if %0 >= 3
  2206                              <2>  mov ecx, %3
  2207                              <2>  %if %0 = 4
  2208                              <2>  mov edx, %4
  2209                              <2>  %endif
  2210                              <2>  %endif
  2211                              <2>  %endif
  2212 00003369 CD30                <2>  int 30h
  2281 0000336B 7319                <1> 	jnc	short panic
  2282                              <1> 	;
  2283 0000336D BE[9C680000]        <1> 	mov	esi, etc_init_err_msg
  2284                              <1> 	; 08/01/2022
  2285                              <1> 	;call 	print_msg
  2286 00003372 EB17                <1> 	jmp	short key_to_reboot
  2287                              <1> 
  2288                              <1> ;align 4
  2289                              <1> init_argp:
  2290 00003374 [7C330000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2291                              <1> init_file:
  2292                              <1> 	; 24/08/2015
  2293 0000337C 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2293 00003385 00                  <1>
  2294                              <1> panic:
  2295                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2296                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2297 00003386 BE[81680000]        <1> 	mov 	esi, panic_msg
  2298                              <1> key_to_reboot: ; 08/01/2022 (Retro UNIX 386 v1.1)
  2299 0000338B E819000000          <1> 	call 	print_msg
  2300                              <1> ;key_to_reboot:
  2301                              <1> 	; 15/11/2015
  2302 00003390 E8832C0000          <1> 	call 	getch 
  2303                              <1> 		; wait for a character from the current tty
  2304                              <1> 	;
  2305 00003395 B00A                <1> 	mov	al, 0Ah
  2306 00003397 8A1D[B66B0000]      <1> 	mov	bl, [ptty] ; [active_page]
  2307 0000339D B407                <1> 	mov	ah, 07h ; Black background, 
  2308                              <1> 			; light gray forecolor
  2309 0000339F E821E0FFFF          <1> 	call 	write_tty
  2310 000033A4 E9BCDCFFFF          <1> 	jmp	cpu_reset 
  2311                              <1> 
  2312                              <1> print_msg:
  2313                              <1> 	; 01/07/2015
  2314                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2315                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2316                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2317                              <1> 	;
  2318                              <1> 	;
  2319 000033A9 AC                  <1> 	lodsb
  2320                              <1> pmsg1:
  2321 000033AA 56                  <1> 	push 	esi
  2322 000033AB 0FB61D[B66B0000]    <1> 	movzx	ebx, byte [ptty]
  2323 000033B2 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2324 000033B4 E80CE0FFFF          <1> 	call 	write_tty
  2325 000033B9 5E                  <1> 	pop	esi
  2326 000033BA AC                  <1> 	lodsb
  2327 000033BB 20C0                <1> 	and 	al, al
  2328 000033BD 75EB                <1> 	jnz 	short pmsg1
  2329 000033BF C3                  <1> 	retn
  2330                              <1> 	
  2331                              <1> ctrlbrk:
  2332                              <1> 	; 04/02/2022
  2333                              <1> 	; 01/02/2022
  2334                              <1> 	; 12/11/2015
  2335                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2336                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2337                              <1> 	;
  2338                              <1> 	; INT 1Bh (control+break) handler
  2339                              <1> 	;
  2340                              <1>       	; Retro Unix 8086 v1 feature only!
  2341                              <1>       	;
  2342 000033C0 66833D[906F0000]00  <1> 	cmp 	word [u.intr], 0
  2343 000033C8 764B                <1> 	jna 	short cbrk4
  2344                              <1> cbrk0:
  2345                              <1> 	; 12/11/2015
  2346                              <1> 	; 06/12/2013
  2347 000033CA 66833D[926F0000]00  <1> 	cmp 	word [u.quit], 0
  2348 000033D2 7441                <1> 	jz	short cbrk4
  2349                              <1> 	;
  2350                              <1> 	; 20/09/2013	
  2351                              <1> 	;push 	ax
  2352                              <1> 	; 01/02/2022
  2353 000033D4 50                  <1> 	push	eax
  2354                              <1> 
  2355                              <1> 	; 04/02/2022
  2356                              <1> 	; (repetitive ctrl+brk check) 
  2357 000033D5 66A1[926F0000]      <1> 	mov	ax, [u.quit]
  2358 000033DB 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2359 000033DD 7435                <1> 	jz	short cbrk3
  2360                              <1> 
  2361                              <1> 	; 20/09/2013
  2362 000033DF A0[B66B0000]        <1> 	mov	al, [ptty]
  2363                              <1> 	;
  2364                              <1> 	; 12/11/2015
  2365                              <1> 	;
  2366                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2367                              <1> 	; or ctrl+break from console (pseudo) tty
  2368                              <1> 	; (!redirection!)
  2369                              <1> 	;
  2370 000033E4 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2371 000033E6 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2372                              <1> 	;	
  2373                              <1> 	; Serial port interrupt handler sets [ptty]
  2374                              <1> 	; to the port's tty number (as temporary).
  2375                              <1> 	;
  2376                              <1> 	; If active process is using a stdin or 
  2377                              <1> 	; stdout redirection (by the shell),
  2378                              <1>         ; console tty keyboard must be available
  2379                              <1> 	; to terminate running process,
  2380                              <1> 	; in order to prevent a deadlock. 
  2381                              <1> 	;
  2382 000033E8 52                  <1> 	push	edx
  2383 000033E9 0FB615[9B6F0000]    <1> 	movzx	edx, byte [u.uno]
  2384 000033F0 3A82[A76C0000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2385 000033F6 5A                  <1> 	pop	edx
  2386 000033F7 7412                <1> 	je	short cbrk2
  2387                              <1> cbrk1:
  2388 000033F9 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2389                              <1> 	; 06/12/2013
  2390 000033FB 3A05[7C6F0000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2391 00003401 7408                <1> 	je	short cbrk2	
  2392 00003403 3A05[7D6F0000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2393 00003409 7509                <1> 	jne	short cbrk3	
  2394                              <1> cbrk2:
  2395                              <1> 	;; 06/12/2013
  2396                              <1> 	;mov	ax, [u.quit]
  2397                              <1> 	;and	ax, ax
  2398                              <1> 	;jz	short cbrk3
  2399                              <1> 	;
  2400                              <1> 	;xor	ax, ax ; 0
  2401                              <1> 	;dec	ax
  2402                              <1> 	; 01/02/2022
  2403 0000340B 31C0                <1> 	xor	eax, eax ; 0
  2404 0000340D 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2405                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2406 0000340E 66A3[926F0000]      <1> 	mov	[u.quit], ax
  2407                              <1> cbrk3:
  2408                              <1> 	;pop	ax
  2409                              <1> 	; 01/02/2022
  2410 00003414 58                  <1> 	pop	eax
  2411                              <1> cbrk4:
  2412 00003415 C3                  <1> 	retn
  2413                              <1> 
  2414                              <1> com2_int:
  2415                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2416                              <1> 	; 07/11/2015 
  2417                              <1> 	; 24/10/2015
  2418                              <1> 	; 23/10/2015
  2419                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2420                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2421                              <1> 	; < serial port 2 interrupt handler >
  2422                              <1> 	;
  2423 00003416 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2424                              <1> 	;;push	eax
  2425                              <1> 	; 08/01/2022
  2426 00003419 29C0                <1> 	sub	eax, eax
  2427 0000341B B009                <1> 	mov	al, 9
  2428                              <1> 	;mov	ax, 9
  2429 0000341D EB07                <1> 	jmp	short comm_int
  2430                              <1> com1_int:
  2431                              <1> 	; 07/11/2015
  2432                              <1> 	; 24/10/2015
  2433 0000341F 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2434                              <1> 	; 23/10/2015
  2435                              <1> 	;push	eax
  2436                              <1> 	; 08/01/2022
  2437 00003422 29C0                <1> 	sub	eax, eax
  2438 00003424 B008                <1> 	mov	al, 8
  2439                              <1> 	;mov	ax, 8
  2440                              <1> comm_int:
  2441                              <1> 	; 08/01/2022
  2442                              <1> 	; 20/11/2015
  2443                              <1> 	; 18/11/2015
  2444                              <1> 	; 17/11/2015
  2445                              <1> 	; 16/11/2015
  2446                              <1> 	; 09/11/2015
  2447                              <1> 	; 08/11/2015
  2448                              <1> 	; 07/11/2015
  2449                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2450                              <1> 	; 01/11/2015
  2451                              <1> 	; 26/10/2015
  2452                              <1> 	; 23/10/2015
  2453 00003426 53                  <1> 	push	ebx
  2454 00003427 56                  <1> 	push	esi
  2455 00003428 57                  <1> 	push	edi
  2456 00003429 1E                  <1> 	push 	ds
  2457 0000342A 06                  <1> 	push 	es
  2458                              <1> 	; 18/11/2015
  2459 0000342B 0F20DB              <1> 	mov	ebx, cr3
  2460 0000342E 53                  <1> 	push	ebx ; ****
  2461                              <1> 	;
  2462 0000342F 51                  <1> 	push	ecx ; ***
  2463 00003430 52                  <1> 	push	edx ; **
  2464                              <1> 	;
  2465 00003431 BB10000000          <1> 	mov	ebx, KDATA
  2466 00003436 8EDB                <1> 	mov	ds, bx
  2467 00003438 8EC3                <1> 	mov	es, bx
  2468                              <1> 	;
  2469 0000343A 8B0D[886B0000]      <1> 	mov	ecx, [k_page_dir]
  2470 00003440 0F22D9              <1> 	mov	cr3, ecx
  2471                              <1> 	; 20/11/2015
  2472                              <1> 	; Interrupt identification register
  2473 00003443 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2474                              <1> 	;
  2475 00003447 3C08                <1> 	cmp 	al, 8 
  2476 00003449 7702                <1> 	ja 	short com_i0
  2477                              <1> 	;
  2478                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2479                              <1> 	; 20/11/2015
  2480                              <1> 	; 17/11/2015
  2481                              <1> 	; 16/11/2015
  2482                              <1> 	; 15/11/2015
  2483                              <1> 	; 24/10/2015
  2484                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2485                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2486                              <1> 	; < serial port 1 interrupt handler >
  2487                              <1> 	;
  2488 0000344B FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2489                              <1> com_i0:
  2490                              <1> 	;push	eax ; *
  2491                              <1> 	; 07/11/2015
  2492 0000344D A2[F66B0000]        <1> 	mov 	byte [ccomport], al
  2493                              <1> 	; 09/11/2015
  2494                              <1> 	;movzx	ebx, ax ; 8 or 9
  2495                              <1> 	; 08/01/2022
  2496 00003452 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2497                              <1> 	; 17/11/2015
  2498                              <1>  	; reset request for response status
  2499 00003454 88A3[EC6B0000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2500                              <1> 	;
  2501                              <1> 	; 20/11/2015
  2502 0000345A EC                  <1> 	in	al, dx		; read interrupt id. register
  2503 0000345B EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2504 0000345D 2404                <1> 	and	al, 4		; received data available?	
  2505 0000345F 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2506                              <1> 	;
  2507                              <1> 	; 20/11/2015
  2508 00003461 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2509 00003464 EC                  <1> 	in	al, dx     	; read character
  2510                              <1> 	;JMP	$+2	   	; I/O DELAY
  2511                              <1> 	; 08/11/2015
  2512                              <1> 	; 07/11/2015
  2513 00003465 89DE                <1> 	mov	esi, ebx 
  2514 00003467 89DF                <1> 	mov	edi, ebx
  2515 00003469 81C6[F06B0000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2516 0000346F 81C7[F26B0000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2517 00003475 8806                <1> 	mov	[esi], al ; received char (current char)
  2518                              <1> 	; query
  2519 00003477 20C0                <1> 	and	al, al
  2520 00003479 7527                <1> 	jnz	short com_i2
  2521                              <1>    	; response
  2522                              <1> 	; 17/11/2015
  2523                              <1> 	; set request for response status
  2524 0000347B FE83[EC6B0000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2525                              <1> 	;
  2526 00003481 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2527 00003485 EC                  <1> 	in	al, dx	   	; read line status register 
  2528 00003486 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2529 00003488 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2530 0000348A 7445                <1> 	jz	short com_eoi 	; no
  2531 0000348C B0FF                <1> 	mov 	al, 0FFh   	; response			
  2532 0000348E 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2533 00003492 EE                  <1> 	out	dx, al	   	; send on serial port
  2534                              <1> 	; 17/11/2015
  2535 00003493 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2536 00003496 7502                <1> 	jne 	short com_i1    ; no
  2537 00003498 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2538                              <1> com_i1:
  2539                              <1> 	; 17/11/2015
  2540                              <1> 	; reset request for response status (again)
  2541 0000349A FE8B[EC6B0000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2542 000034A0 EB2F                <1> 	jmp	short com_eoi
  2543                              <1> com_i2:	
  2544                              <1> 	; 08/11/2015
  2545 000034A2 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2546 000034A4 7417                <1> 	je	short com_i3	; (check for response signal)
  2547                              <1> 	; 07/11/2015
  2548 000034A6 3C04                <1> 	cmp	al, 04h	; EOT
  2549 000034A8 751C                <1> 	jne	short com_i4	
  2550                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2551                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2552                              <1> 	; 08/11/2015
  2553                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2554 000034AA 861D[B66B0000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2555 000034B0 E80BFFFFFF          <1> 	call 	ctrlbrk
  2556 000034B5 861D[B66B0000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2557                              <1> 	;mov	al, 04h ; EOT
  2558                              <1> 	; 08/11/2015
  2559 000034BB EB09                <1> 	jmp	short com_i4	
  2560                              <1> com_i3:
  2561                              <1> 	; 08/11/2015
  2562                              <1> 	; If 0FFh has been received just after a query
  2563                              <1> 	; (schar, ZERO), it is a response signal.
  2564                              <1> 	; 17/11/2015
  2565 000034BD 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2566 000034C0 7704                <1> 	ja	short com_i4 ; no
  2567                              <1> 	; reset query status (schar)
  2568 000034C2 8807                <1> 	mov	[edi], al ; 0FFh
  2569 000034C4 FEC0                <1> 	inc	al ; 0
  2570                              <1> com_i4:
  2571                              <1> 	; 27/07/2014
  2572                              <1> 	; 09/07/2014
  2573 000034C6 D0E3                <1> 	shl	bl, 1	
  2574 000034C8 81C3[B86B0000]      <1> 	add	ebx, ttychr
  2575                              <1> 	; 23/07/2014 (always overwrite)
  2576                              <1> 	;;cmp	word [ebx], 0
  2577                              <1> 	;;ja	short com_eoi
  2578                              <1> 	;
  2579 000034CE 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2580                              <1> 			    ; scan code = 0
  2581                              <1> com_eoi:
  2582                              <1> 	;mov	al, 20h
  2583                              <1> 	;out	20h, al	   ; end of interrupt
  2584                              <1> 	;
  2585                              <1> 	; 07/11/2015
  2586                              <1>       	;pop	eax ; *
  2587 000034D1 A0[F66B0000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2588                              <1> 	; al = tty number (8 or 9)
  2589 000034D6 E8FA1A0000          <1>         call	wakeup
  2590                              <1> com_iret:
  2591                              <1> 	; 23/10/2015
  2592 000034DB 5A                  <1> 	pop	edx ; **
  2593 000034DC 59                  <1> 	pop	ecx ; ***
  2594                              <1> 	; 18/11/2015
  2595                              <1> 	;pop	eax ; ****
  2596                              <1> 	;mov	cr3, eax
  2597                              <1> 	;jmp	iiret
  2598 000034DD E9C1D4FFFF          <1> 	jmp	iiretp
  2599                              <1> 
  2600                              <1> ;iiretp: ; 01/09/2015
  2601                              <1> ;	; 28/08/2015
  2602                              <1> ;	pop	eax ; (*) page directory
  2603                              <1> ;	mov	cr3, eax
  2604                              <1> ;iiret:
  2605                              <1> ;	; 22/08/2014
  2606                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2607                              <1> ;	out	20h, al	; 8259 PORT
  2608                              <1> ;	;
  2609                              <1> ;	pop	es
  2610                              <1> ;	pop	ds
  2611                              <1> ;	pop	edi
  2612                              <1> ;	pop	esi
  2613                              <1> ;	pop	ebx ; 29/08/2014
  2614                              <1> ;	pop 	eax
  2615                              <1> ;	iretd
  2616                              <1> 
  2617                              <1> sp_init:
  2618                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2619                              <1> 	; 07/11/2015
  2620                              <1> 	; 29/10/2015
  2621                              <1> 	; 26/10/2015
  2622                              <1> 	; 23/10/2015
  2623                              <1> 	; 29/06/2015
  2624                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2625                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2626                              <1> 	; Initialization of Serial Port Communication Parameters
  2627                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2628                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2629                              <1> 	;
  2630                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2631                              <1> 	;
  2632                              <1> 	; INPUT:  (29/06/2015)
  2633                              <1> 	;	AL = 0 for COM1
  2634                              <1> 	;	     1 for COM2
  2635                              <1> 	;	AH = Communication parameters	
  2636                              <1> 	;
  2637                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2638                              <1> 	;	Bit	4	3	2	1	0
  2639                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2640                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2641                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2642                              <1> 	;		11 = even
  2643                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2644                              <1> 	;		Retro UNIX 386 v1 feature only !
  2645                              <1> 	;	Bit	7    6    5  | Baud rate
  2646                              <1> 	;		------------------------
  2647                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2648                              <1> 	;		0    0    1  | 9600 (12)
  2649                              <1> 	;		0    1    0  | 19200 (6) 
  2650                              <1> 	;		0    1	  1  | 38400 (3) 
  2651                              <1> 	;		1    0	  0  | 14400 (8)
  2652                              <1> 	;		1    0	  1  | 28800 (4)
  2653                              <1> 	;		1    1    0  | 57600 (2)
  2654                              <1> 	;		1    1    1  | 115200 (1) 	
  2655                              <1> 	
  2656                              <1> 	; References:	
  2657                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2658                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2659                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2660                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2661                              <1> 	;
  2662                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2663                              <1> 	;
  2664 000034E2 BB[F26B0000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2665 000034E7 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2666                              <1> 	; 29/10/2015
  2667 000034EB 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2668 000034EF E84F000000          <1> 	call	sp_i3	; call A4	
  2669 000034F4 A880                <1> 	test	al, 80h
  2670 000034F6 740E                <1> 	jz	short sp_i0 ; OK..
  2671                              <1> 		; Error !
  2672                              <1> 	;mov	dx, 3F8h
  2673 000034F8 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2674                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2675                              <1> 	; 08/01/2022
  2676 000034FB B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2677 000034FD E841000000          <1> 	call	sp_i3	; call A4	
  2678 00003502 A880                <1> 	test	al, 80h
  2679 00003504 7508                <1> 	jnz	short sp_i1
  2680                              <1> sp_i0:
  2681                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2682                              <1>         ; (INT 14h initialization code disables interrupts.)
  2683                              <1> 	;
  2684 00003506 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2685 00003509 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2686                              <1> sp_i1:
  2687 0000350E 43                  <1> 	inc	ebx
  2688 0000350F 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2689                              <1> 	; 29/10/2015
  2690                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2691                              <1> 	; 08/01/2022
  2692 00003513 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2693 00003515 E829000000          <1> 	call	sp_i3	; call A4	
  2694 0000351A A880                <1> 	test	al, 80h
  2695 0000351C 740E                <1> 	jz	short sp_i2 ; OK..
  2696                              <1> 		; Error !
  2697                              <1> 	;mov	dx, 2F8h
  2698 0000351E 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2699                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2700                              <1> 	; 08/01/2022
  2701 00003521 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2702 00003523 E81B000000          <1> 	call	sp_i3	; call A4	
  2703 00003528 A880                <1> 	test	al, 80h
  2704 0000352A 7516                <1> 	jnz	short sp_i7
  2705                              <1> sp_i2:
  2706 0000352C C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2707                              <1> sp_i6:
  2708                              <1> 	;; COM2 - enabling IRQ 3
  2709                              <1> 	; 08/01/2022
  2710 0000352F B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2711                              <1> 	; 07/11/2015
  2712                              <1> 	; 26/10/2015
  2713                              <1> 	;pushf
  2714                              <1> 	;cli
  2715                              <1> 	;;
  2716                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2717                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2718                              <1> 	;in	al, dx 	   		; read register
  2719                              <1> 	;JMP	$+2	   		; I/O DELAY
  2720                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2721                              <1> 	;out	dx, al     		; write back to register
  2722                              <1> 	;JMP	$+2	   		; I/O DELAY
  2723                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2724                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2725                              <1> 	;in	al, dx     		; read register
  2726                              <1> 	;JMP	$+2	   		; I/O DELAY
  2727                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2728                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2729                              <1> 	;out	dx, al 	   		; write back to register
  2730                              <1> 	;JMP	$+2        		; I/O DELAY
  2731                              <1> 	;in	al, 21h    		; read interrupt mask register
  2732                              <1> 	;JMP	$+2	   		; I/O DELAY
  2733                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2734                              <1> 	;out	21h, al    		; write back to register
  2735                              <1> 	;
  2736                              <1> 	; 08/01/2022
  2737 00003531 9C                  <1> 	pushf
  2738 00003532 E8AA000000          <1> 	call	sp_i8
  2739                              <1> 	; 23/10/2015
  2740 00003537 B8[16340000]        <1> 	mov 	eax, com2_int
  2741 0000353C A3[CA390000]        <1> 	mov	[com2_irq3], eax
  2742                              <1> 	; 26/10/2015
  2743 00003541 9D                  <1> 	popf	
  2744                              <1> sp_i7:
  2745 00003542 C3                  <1> 	retn
  2746                              <1> 
  2747                              <1> sp_i3:
  2748                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2749                              <1> 	; 28/10/2015
  2750 00003543 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2751 00003545 B000                <1> 	mov	al, 0
  2752 00003547 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2753 00003548 EB00                <1> 	JMP	$+2			; I/O DELAY
  2754 0000354A 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2755 0000354D B080                <1> 	mov	al, 80h			
  2756 0000354F EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2757                              <1> 	;-----	SET BAUD RATE DIVISOR
  2758                              <1> 	; 26/10/2015
  2759 00003550 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2760                              <1> 					; of the divisor value
  2761 00003553 88C8                <1> 	mov	al, cl	; 1
  2762 00003555 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2763                              <1> 					; 2 = 57600 baud
  2764                              <1> 					; 3 = 38400 baud
  2765                              <1> 					; 6 = 19200 baud
  2766                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2767 00003556 EB00                <1> 	JMP	$+2			; I/O DELAY
  2768 00003558 28C0                <1> 	sub	al, al
  2769 0000355A FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2770                              <1> 					; of the divisor value
  2771 0000355C EE                  <1> 	out	dx, al ; 0
  2772 0000355D EB00                <1> 	JMP	$+2			; I/O DELAY
  2773                              <1> 	;	
  2774 0000355F 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2775                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2776 00003561 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2777 00003564 EE                  <1> 	out	dx, al			
  2778 00003565 EB00                <1> 	JMP	$+2			; I/O DELAY
  2779                              <1> 	; 29/10/2015
  2780 00003567 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2781 00003569 30C0                <1> 	xor	al, al			; 0
  2782 0000356B EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2783 0000356C EB00                <1> 	JMP	$+2	
  2784                              <1> sp_i4:
  2785                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2786                              <1> 	; 29/06/2015 (line status after modem status)
  2787 0000356E 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2788                              <1> sp_i4s:
  2789 00003571 EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2790 00003572 EB00                <1> 	JMP	$+2			; I/O DELAY
  2791 00003574 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2792 00003576 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2793                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2794 00003578 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2795                              <1> 	; AL = Line status, AH = Modem status
  2796 00003579 C3                  <1> 	retn
  2797                              <1> 
  2798                              <1> sp_status:
  2799                              <1> 	; 29/06/2015
  2800                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2801                              <1> 	; Get serial port status
  2802 0000357A 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2803 0000357E 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2804                              <1> 					; dx = 2FEh for COM2
  2805 00003580 EBEF                <1> 	jmp	short sp_i4s
  2806                              <1> 
  2807                              <1> sp_setp: ; Set serial port communication parameters
  2808                              <1> 	; 08/01/2022
  2809                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2810                              <1> 	; 07/11/2015
  2811                              <1> 	; 29/10/2015
  2812                              <1> 	; 29/06/2015
  2813                              <1> 	; Retro UNIX 386 v1 feature only !	
  2814                              <1> 	;
  2815                              <1> 	; INPUT:
  2816                              <1> 	;	AL = 0 for COM1
  2817                              <1> 	;	     1 for COM2
  2818                              <1> 	;	AH = Communication parameters (*)
  2819                              <1> 	; OUTPUT:
  2820                              <1> 	;	CL = Line status
  2821                              <1> 	;	CH = Modem status
  2822                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2823                              <1> 	;		 'invalid parameter !' 
  2824                              <1> 	;		 	 or
  2825                              <1> 	;		 'device not ready !' error
  2826                              <1> 	;	
  2827                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2828                              <1> 	;	Bit	4	3	2	1	0
  2829                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2830                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2831                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2832                              <1> 	;		11 = even
  2833                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2834                              <1> 	;		Retro UNIX 386 v1 feature only !
  2835                              <1> 	;	Bit	7    6    5  | Baud rate
  2836                              <1> 	;		------------------------
  2837                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2838                              <1> 	;		0    0    1  | 9600 (12)
  2839                              <1> 	;		0    1    0  | 19200 (6) 
  2840                              <1> 	;		0    1	  1  | 38400 (3) 
  2841                              <1> 	;		1    0	  0  | 14400 (8)
  2842                              <1> 	;		1    0	  1  | 28800 (4)
  2843                              <1> 	;		1    1    0  | 57600 (2)
  2844                              <1> 	;		1    1    1  | 115200 (1) 
  2845                              <1> 	;
  2846                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2847                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2848                              <1> 	;
  2849                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2850                              <1> 	;
  2851 00003582 66BAF803            <1> 	mov	dx, 3F8h
  2852 00003586 BB[F26B0000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2853 0000358B 3C01                <1> 	cmp	al, 1
  2854 0000358D 7770                <1> 	ja 	short sp_invp_err
  2855 0000358F 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2856 00003591 FECE                <1> 	dec	dh ; 2F8h
  2857 00003593 43                  <1> 	inc	ebx ; COM2 control byte offset
  2858                              <1> sp_setp1:
  2859                              <1> 	; 29/10/2015
  2860 00003594 8823                <1> 	mov	[ebx], ah
  2861 00003596 0FB6CC              <1> 	movzx 	ecx, ah
  2862 00003599 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2863 0000359C 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2864 0000359F 8A81[0E360000]      <1> 	mov	al, [ecx+b_div_tbl]
  2865 000035A5 6689C1              <1> 	mov	cx, ax
  2866 000035A8 E896FFFFFF          <1> 	call	sp_i3
  2867 000035AD 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2868 000035B0 A880                <1> 	test	al, 80h
  2869 000035B2 740F                <1> 	jz	short sp_setp2
  2870 000035B4 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2871                              <1> stp_dnr_err:
  2872 000035B7 C705[A16F0000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2872 000035BF 0000                <1>
  2873                              <1> 	; CL = Line status, CH = Modem status
  2874 000035C1 F9                  <1> 	stc
  2875 000035C2 C3                  <1> 	retn
  2876                              <1> sp_setp2:
  2877 000035C3 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2878                              <1>         ;jna	sp_i6
  2879                              <1> 		      ; COM1 (3F?h)
  2880                              <1> 	; 24/12/2021
  2881 000035C6 7705                <1> 	ja	short sp_i5
  2882 000035C8 E962FFFFFF          <1> 	jmp	sp_i6
  2883                              <1> sp_i5: 
  2884                              <1> 	; 08/01/2022
  2885 000035CD B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2886                              <1> 	; 07/11/2015
  2887                              <1> 	; 26/10/2015
  2888                              <1> 	; 29/06/2015
  2889                              <1> 	;
  2890                              <1> 	;; COM1 - enabling IRQ 4
  2891                              <1> 	;pushf
  2892                              <1> 	;cli
  2893                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2894                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2895                              <1> 	;in	al, dx 	   		; read register
  2896                              <1> 	;JMP	$+2			; I/O DELAY
  2897                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2898                              <1> 	;out	dx, al     		; write back to register
  2899                              <1> 	;JMP	$+2			; I/O DELAY
  2900                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2901                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2902                              <1> 	;in	al, dx     		; read register
  2903                              <1> 	;JMP	$+2			; I/O DELAY
  2904                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2905                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2906                              <1> 	;out	dx, al 	   		; write back to register
  2907                              <1> 	;JMP	$+2        		; I/O DELAY
  2908                              <1> 	;in	al, 21h    		; read interrupt mask register
  2909                              <1> 	;JMP	$+2			; I/O DELAY
  2910                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2911                              <1> 	;out	21h, al    		; write back to register
  2912                              <1> 	;
  2913                              <1> 	; 08/01/2022
  2914 000035CF 9C                  <1> 	pushf
  2915 000035D0 E80C000000          <1> 	call	sp_i8
  2916                              <1> 	; 23/10/2015
  2917 000035D5 B8[1F340000]        <1> 	mov 	eax, com1_int
  2918 000035DA A3[C6390000]        <1> 	mov	[com1_irq4], eax
  2919                              <1> 	; 26/10/2015
  2920 000035DF 9D                  <1> 	popf
  2921 000035E0 C3                  <1> 	retn
  2922                              <1> 
  2923                              <1> sp_i8:
  2924                              <1> 	; 08/01/2022
  2925                              <1> 	;pushf
  2926 000035E1 FA                  <1> 	cli
  2927                              <1> 	;
  2928                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2929 000035E2 B2FC                <1> 	mov	dl, 0FCh
  2930 000035E4 EC                  <1> 	in	al, dx 	   		; read register
  2931 000035E5 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2932 000035E7 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2933 000035E9 EE                  <1> 	out	dx, al     		; write back to register
  2934 000035EA EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2935                              <1> 	;mov	dx, 2F9h  ; 3F9h 	; interrupt enable register
  2936 000035EC B2F9                <1> 	mov	dl, 0F9h
  2937 000035EE EC                  <1> 	in	al, dx     		; read register
  2938 000035EF EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2939                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2940 000035F1 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2941 000035F3 EE                  <1> 	out	dx, al 	   		; write back to register
  2942 000035F4 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2943 000035F6 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2944 000035F8 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2945                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2946 000035FA 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2947 000035FC E621                <1> 	out	21h, al    		; write back to register
  2948                              <1> 	;
  2949                              <1> 	;popf	
  2950 000035FE C3                  <1> 	retn
  2951                              <1> 
  2952                              <1> sp_invp_err:
  2953 000035FF C705[A16F0000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2953 00003607 0000                <1>
  2954 00003609 31C9                <1> 	xor	ecx, ecx
  2955 0000360B 49                  <1> 	dec	ecx ; 0FFFFh
  2956 0000360C F9                  <1> 	stc
  2957 0000360D C3                  <1> 	retn
  2958                              <1> 
  2959                              <1> ; 29/10/2015
  2960                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2961 0000360E 010C0603080401      <1> 	db	1, 12, 6, 3, 8, 4, 1
  2962                              <1> 
  2963                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2964                              <1> epoch:
  2965                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2966                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2967                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2968                              <1> 	; 'epoch' procedure prototype: 
  2969                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2970                              <1> 	; 14/11/2012
  2971                              <1> 	; unixboot.asm (boot file configuration)
  2972                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2973                              <1> 	; 21/7/2012
  2974                              <1> 	; 15/7/2012
  2975                              <1> 	; 14/7/2012		
  2976                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2977                              <1> 	; compute current date and time as UNIX Epoch/Time
  2978                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2979                              <1> 	;
  2980                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2981                              <1> 	;
  2982 00003615 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2983 0000361A 86E9                <1>         xchg 	ch,cl
  2984 0000361C 66890D[F4680000]    <1>         mov 	[hour], cx
  2985 00003623 86F2                <1>         xchg 	dh,dl
  2986 00003625 668915[F6680000]    <1>         mov 	[second], dx
  2987                              <1> 	;
  2988 0000362C E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2989 00003631 86E9                <1>         xchg 	ch,cl
  2990 00003633 66890D[F0680000]    <1>         mov 	[year], cx
  2991 0000363A 86F2                <1>         xchg 	dh,dl
  2992 0000363C 668915[F2680000]    <1>         mov 	[month], dx
  2993                              <1> 	;
  2994 00003643 66B93030            <1> 	mov 	cx, 3030h
  2995                              <1> 	;
  2996 00003647 A0[F4680000]        <1> 	mov 	al, [hour] ; Hour
  2997                              <1>         	; AL <= BCD number)
  2998 0000364C D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2999                              <1> 					; AH = AL / 10h
  3000                              <1> 					; AL = AL MOD 10h
  3001 0000364E D50A                <1>         aad 	; AX= AH*10+AL
  3002 00003650 A2[F4680000]        <1> 	mov 	[hour], al
  3003 00003655 A0[F5680000]        <1> 	mov 	al, [hour+1] ; Minute
  3004                              <1>         	; AL <= BCD number)
  3005 0000365A D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3006                              <1> 					; AH = AL / 10h
  3007                              <1> 					; AL = AL MOD 10h
  3008 0000365C D50A                <1>         aad 	; AX= AH*10+AL
  3009 0000365E A2[F5680000]        <1> 	mov 	[minute], al
  3010 00003663 A0[F6680000]        <1> 	mov 	al, [second] ; Second
  3011                              <1>         	; AL <= BCD number)
  3012 00003668 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3013                              <1> 					; AH = AL / 10h
  3014                              <1> 					; AL = AL MOD 10h
  3015 0000366A D50A                <1>         aad 	; AX= AH*10+AL
  3016 0000366C A2[F6680000]        <1> 	mov 	[second], al
  3017 00003671 66A1[F0680000]      <1> 	mov 	ax, [year] ; Year (century)
  3018                              <1>  	;push 	ax
  3019                              <1> 	; 08/01/2022
  3020 00003677 50                  <1> 	push	eax
  3021                              <1> 	   	; AL <= BCD number)
  3022 00003678 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3023                              <1> 					; AH = AL / 10h
  3024                              <1> 					; AL = AL MOD 10h
  3025 0000367A D50A                <1>         aad 	; AX= AH*10+AL
  3026 0000367C B464                <1> 	mov 	ah, 100
  3027 0000367E F6E4                <1> 	mul 	ah
  3028 00003680 66A3[F0680000]      <1> 	mov 	[year], ax
  3029                              <1> 	;pop	ax
  3030                              <1> 	; 08/01/2022
  3031 00003686 58                  <1> 	pop	eax
  3032 00003687 88E0                <1> 	mov	al, ah
  3033                              <1>         	; AL <= BCD number)
  3034 00003689 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3035                              <1> 					; AH = AL / 10h
  3036                              <1> 					; AL = AL MOD 10h
  3037 0000368B D50A                <1>         aad 	; AX= AH*10+AL
  3038 0000368D 660105[F0680000]    <1> 	add 	[year], ax
  3039 00003694 A0[F2680000]        <1> 	mov 	al, [month] ; Month
  3040                              <1>            	; AL <= BCD number)
  3041 00003699 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3042                              <1> 					; AH = AL / 10h
  3043                              <1> 					; AL = AL MOD 10h
  3044 0000369B D50A                <1>         aad 	; AX= AH*10+AL
  3045 0000369D A2[F2680000]        <1> 	mov 	[month], al	
  3046 000036A2 A0[F3680000]        <1>         mov     al, [month+1]      	; Day
  3047                              <1>            	; AL <= BCD number)
  3048 000036A7 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3049                              <1> 					; AH = AL / 10h
  3050                              <1> 					; AL = AL MOD 10h
  3051 000036A9 D50A                <1>         aad 	; AX= AH*10+AL
  3052 000036AB A2[F3680000]        <1>         mov     [day], al
  3053                              <1> 	
  3054                              <1> convert_to_epoch:
  3055                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3056                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1)
  3057                              <1> 	;
  3058                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3059                              <1> 	;
  3060                              <1> 	; Derived from DALLAS Semiconductor
  3061                              <1> 	; Application Note 31 (DS1602/DS1603)
  3062                              <1> 	; 6 May 1998
  3063 000036B0 29C0                <1> 	sub 	eax, eax
  3064 000036B2 66A1[F0680000]      <1> 	mov 	ax, [year]
  3065 000036B8 662DB207            <1> 	sub 	ax, 1970
  3066 000036BC BA6D010000          <1> 	mov 	edx, 365
  3067 000036C1 F7E2                <1> 	mul 	edx
  3068 000036C3 31DB                <1> 	xor 	ebx, ebx
  3069 000036C5 8A1D[F2680000]      <1> 	mov 	bl, [month]
  3070 000036CB FECB                <1> 	dec 	bl
  3071 000036CD D0E3                <1> 	shl 	bl, 1
  3072                              <1> 	;sub	edx, edx
  3073 000036CF 668B93[F8680000]    <1> 	mov 	dx, [EBX+DMonth]
  3074 000036D6 8A1D[F3680000]      <1>         mov     bl, [day]
  3075 000036DC FECB                <1> 	dec 	bl
  3076 000036DE 01D0                <1> 	add 	eax, edx
  3077 000036E0 01D8                <1> 	add 	eax, ebx
  3078                              <1> 			; EAX = days since 1/1/1970
  3079 000036E2 668B15[F0680000]    <1> 	mov 	dx, [year]
  3080 000036E9 6681EAB107          <1> 	sub 	dx, 1969
  3081 000036EE 66D1EA              <1> 	shr 	dx, 1
  3082 000036F1 66D1EA              <1> 	shr 	dx, 1		
  3083                              <1> 		; (year-1969)/4
  3084 000036F4 01D0                <1> 	add 	eax, edx
  3085                              <1> 			; + leap days since 1/1/1970
  3086 000036F6 803D[F2680000]02    <1> 	cmp 	byte [month], 2	; if past february
  3087 000036FD 7610                <1> 	jna 	short cte1
  3088 000036FF 668B15[F0680000]    <1> 	mov 	dx, [year]
  3089 00003706 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3090 0000370A 7503                <1> 	jnz 	short cte1		
  3091                              <1> 			; and if leap year
  3092 0000370C 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3093                              <1> cte1: 			; compute seconds since 1/1/1970
  3094 0000370F BA18000000          <1> 	mov 	edx, 24
  3095 00003714 F7E2                <1> 	mul	edx
  3096 00003716 8A15[F4680000]      <1> 	mov 	dl, [hour]
  3097 0000371C 01D0                <1> 	add 	eax, edx
  3098                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3099                              <1> 	;mov	ebx, 60
  3100 0000371E B33C                <1> 	mov	bl, 60
  3101 00003720 F7E3                <1> 	mul	ebx
  3102 00003722 8A15[F5680000]      <1> 	mov 	dl, [minute]
  3103 00003728 01D0                <1> 	add 	eax, edx
  3104                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3105                              <1> 	;mov 	ebx, 60
  3106 0000372A F7E3                <1> 	mul	ebx
  3107 0000372C 8A15[F6680000]      <1> 	mov 	dl, [second]
  3108 00003732 01D0                <1> 	add 	eax, edx
  3109                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3110 00003734 C3                  <1> 	retn
  3111                              <1> 
  3112                              <1> get_rtc_time:
  3113                              <1> 	; 15/03/2015
  3114                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3115                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3116                              <1> 	; INT 1Ah
  3117                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3118                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3119                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3120                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3121                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3122                              <1> 	;								
  3123                              <1> RTC_20: 				; GET RTC TIME
  3124 00003735 FA                  <1> 	cli
  3125 00003736 E804D4FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3126 0000373B 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  3127                              <1> 
  3128 0000373D B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  3129 0000373F E8E5D3FFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  3130 00003744 88C6                <1> 	MOV	DH, AL			; SAVE
  3131 00003746 B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  3132 00003748 E8DCD3FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  3133 0000374D 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  3134 0000374F 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  3135 00003751 B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  3136 00003753 E8D1D3FFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  3137 00003758 88C1                <1> 	MOV	CL, AL			; SAVE
  3138 0000375A B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  3139 0000375C E8C8D3FFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  3140 00003761 88C5                <1> 	MOV	CH, AL			; SAVE
  3141 00003763 F8                  <1> 	CLC				; SET CY= 0
  3142                              <1> RTC_29:
  3143 00003764 FB                  <1> 	sti
  3144 00003765 C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  3145                              <1> 
  3146                              <1> get_rtc_date:
  3147                              <1> 	; 15/03/2015
  3148                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3149                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3150                              <1> 	; INT 1Ah
  3151                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3152                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3153                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3154                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3155                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  3156                              <1> 	;
  3157                              <1> RTC_40: 				; GET RTC DATE
  3158 00003766 FA                  <1> 	cli
  3159 00003767 E8D3D3FFFF          <1> 	CALL	UPD_IPR			; CHECK FOR UPDATE IN PROCESS
  3160 0000376C 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  3161                              <1> 
  3162 0000376E B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  3163 00003770 E8B4D3FFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  3164 00003775 88C2                <1> 	MOV	DL, AL			; SAVE
  3165 00003777 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  3166 00003779 E8ABD3FFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  3167 0000377E 88C6                <1> 	MOV	DH, AL			; SAVE
  3168 00003780 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  3169 00003782 E8A2D3FFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  3170 00003787 88C1                <1> 	MOV	CL, AL			; SAVE
  3171 00003789 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  3172 0000378B E899D3FFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  3173 00003790 88C5                <1> 	MOV	CH, AL			; SAVE
  3174 00003792 F8                  <1> 	CLC				; SET CY=0
  3175                              <1> RTC_49:
  3176 00003793 FB                  <1> 	sti
  3177 00003794 C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  3178                              <1> 
  3179                              <1> set_date_time:
  3180                              <1> convert_from_epoch:
  3181                              <1> 	; 02/06/2022
  3182                              <1> 	; 01/06/2022 (BugFix)
  3183                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3184                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3185                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3186                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3187                              <1> 	;
  3188                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3189                              <1> 	;
  3190                              <1> 	; Derived from DALLAS Semiconductor
  3191                              <1> 	; Application Note 31 (DS1602/DS1603)
  3192                              <1> 	; 6 May 1998
  3193                              <1> 	;
  3194                              <1> 	; INPUT:
  3195                              <1> 	; EAX = Unix (Epoch) Time
  3196                              <1> 	;
  3197 00003795 31D2                <1> 	xor 	edx, edx
  3198                              <1> 	; 02/06/2022
  3199 00003797 31C9                <1> 	xor	ecx, ecx
  3200 00003799 31DB                <1> 	xor	ebx, ebx
  3201                              <1> 	;mov 	ecx, 60
  3202 0000379B B13C                <1> 	mov	cl, 60
  3203 0000379D F7F1                <1> 	div	ecx
  3204                              <1> 	;mov 	[imin], eax  ; whole minutes
  3205                              <1> 			     ; since 1/1/1970
  3206                              <1> 	;mov 	[second], dx ; leftover seconds
  3207 0000379F 8815[F6680000]      <1> 	mov	[second], dl ; 02/06/2022
  3208 000037A5 29D2                <1> 	sub 	edx, edx
  3209 000037A7 F7F1                <1> 	div	ecx
  3210                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3211                              <1> 	;		     ; since 1/1/1970
  3212                              <1> 	;mov 	[minute], dx ; leftover minutes
  3213 000037A9 8815[F5680000]      <1> 	mov	[minute], dl ; 02/06/2022
  3214 000037AF 31D2                <1> 	xor	edx, edx
  3215                              <1> 	;mov 	cx, 24
  3216 000037B1 B118                <1> 	mov 	cl, 24
  3217 000037B3 F7F1                <1> 	div	ecx
  3218                              <1> 	;mov 	[iday], ax   ; whole days
  3219                              <1> 			     ; since 1/1/1970
  3220                              <1> 	;mov 	[hour], dx   ; leftover hours
  3221 000037B5 8815[F4680000]      <1> 	mov	[hour], dl   ; 02/06/2022
  3222                              <1> 
  3223 000037BB 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3224                              <1> 			     ; 1/1/1968 	
  3225                              <1> 	;mov 	[iday], ax
  3226 000037C0 50                  <1> 	push 	eax
  3227 000037C1 29D2                <1> 	sub	edx, edx
  3228 000037C3 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3229 000037C8 F7F1                <1> 	div	ecx
  3230 000037CA 59                  <1> 	pop 	ecx
  3231                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3232                              <1> 	;push	dx
  3233                              <1> 	; 01/06/2022
  3234 000037CB 52                  <1> 	push 	edx
  3235                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3236 000037CC 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3237 000037D0 F5                  <1> 	cmc		     ; add this quadyr's leap day
  3238 000037D1 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3239                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3240                              <1> 	;mov 	cx, [iday]
  3241 000037D4 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3242 000037D5 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3243 000037D7 B96D010000          <1> 	mov 	ecx, 365
  3244 000037DC 31D2                <1> 	xor	edx, edx
  3245                              <1> 	; EAX = iday-lday, EDX = 0
  3246 000037DE F7F1                <1> 	div	ecx
  3247                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3248                              <1> 	;jday = iday - (iyrs*365) - lday
  3249                              <1> 	;mov	[jday], dx   ; days since 1/1 of current year
  3250                              <1> 	;add	eax, 1968
  3251 000037E0 6605B007            <1> 	add 	ax, 1968     ; compute year
  3252 000037E4 66A3[F0680000]      <1> 	mov 	[year], ax
  3253                              <1> 	;mov 	cx, dx
  3254                              <1> 	; 02/06/2022
  3255 000037EA 89D1                <1> 	mov	ecx, edx
  3256                              <1> 	;mov 	dx, [qday]
  3257                              <1> 	;pop	dx
  3258                              <1> 	; 01/06/2022
  3259 000037EC 5A                  <1> 	pop 	edx
  3260 000037ED 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3261 000037F2 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3262 000037F4 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3263 000037F8 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3264 000037F9 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3265                              <1> cfe1:			
  3266                              <1> 	;mov 	[jday], cx
  3267                              <1> 	;mov 	bx, 12       ; estimate month
  3268                              <1> 	;sub	ebx, ebx
  3269                              <1> 	; 02/06/2022
  3270 000037FD B30C                <1> 	mov	bl, 12
  3271 000037FF 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3272 00003803 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3273                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3274                              <1> 	;cmp 	cx, dx       ; mday = # of days passed from 1/1
  3275                              <1> 	; 02/06/2022
  3276 00003807 39D1                <1> 	cmp	ecx, edx 	 		
  3277 00003809 7319                <1> 	jnb 	short cfe3
  3278                              <1> 	;dec 	bx           ; month = month - 1
  3279 0000380B FECB                <1> 	dec	bl			
  3280                              <1> 	;shl 	bx, 1
  3281 0000380D D0E3                <1> 	shl	bl, 1
  3282 0000380F 668B93[F8680000]    <1> 	mov 	dx, [ebx+DMonth] ; # elapsed days at 1st of month
  3283                              <1> 	;shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3284                              <1> 	; 02/06/2022
  3285 00003816 D0EB                <1> 	shr	bl, 1
  3286 00003818 80FB01              <1> 	cmp	bl, 1
  3287                              <1> 	;cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3288 0000381B 76EA                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3289 0000381D 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3290 0000381F 75E6                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3291                              <1> 	;inc 	dx           ; mday = mday + 1
  3292 00003821 42                  <1> 	inc	edx
  3293 00003822 EBE3                <1> 	jmp 	short cfe2
  3294                              <1> cfe3:
  3295                              <1> 	;inc 	bx	     ; -> bx = month, 1 to 12
  3296                              <1> 	; 02/06/2022
  3297 00003824 FEC3                <1> 	inc	bl
  3298                              <1> 	;mov 	[month], bx
  3299 00003826 881D[F2680000]      <1> 	mov	[month], bl
  3300                              <1> 	;sub 	cx, dx	     ; day = jday - mday + 1	
  3301 0000382C 29D1                <1> 	sub	ecx, edx
  3302                              <1> 	;inc 	cx 			  
  3303 0000382E FEC1                <1> 	inc	cl
  3304                              <1> 	;mov 	[day], cx
  3305 00003830 880D[F3680000]      <1> 	mov	[day], cl    ; 02/06/2022
  3306                              <1> 	
  3307                              <1> 	; eax, ebx, ecx, edx is changed at return
  3308                              <1> 	; output ->
  3309                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3310                              <1> 
  3311                              <1> 	; 01/06/2022 (BugFix)	
  3312                              <1> _set_date:
  3313 00003836 66A1[F0680000]      <1> 	mov	ax, [year]
  3314 0000383C B520                <1> 	mov	ch, 20h ; century (bcd)
  3315 0000383E 662DD007            <1> 	sub	ax, 2000
  3316 00003842 7306                <1> 	jnc	short set_date
  3317 00003844 B519                <1> 	mov	ch, 19h ; century (bcd) 
  3318 00003846 6683C064            <1> 	add	ax, 100	
  3319                              <1> 	; 01/06/2022
  3320                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3321                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3322                              <1> set_date:
  3323                              <1>         ;mov	al, [year+1]
  3324                              <1> 	;aam 	; ah = al / 10, al = al mod 10
  3325                              <1> 	;db 	0D5h, 10h    ; Undocumented inst. AAD
  3326                              <1> 	;		     ; AL = AH * 10h + AL
  3327                              <1> 	;mov 	ch, al ; century (BCD)
  3328                              <1> 	;mov 	al, [year]
  3329                              <1> 	; al = year (0-99) ; 01/06/2022
  3330 0000384A D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3331 0000384C D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3332                              <1> 			     ; AL = AH * 10h + AL
  3333 0000384E 88C1                <1> 	mov 	cl, al ; year (BCD)
  3334 00003850 A0[F2680000]        <1>         mov 	al, [month]
  3335 00003855 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3336 00003857 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3337                              <1> 			     ; AL = AH * 10h + AL
  3338 00003859 88C6                <1> 	mov 	dh, al ; month (BCD)
  3339 0000385B A0[F3680000]        <1> 	mov 	al, [day]
  3340 00003860 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3341 00003862 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3342                              <1> 			     ; AL = AH * 10h + AL
  3343                              <1> 	; 01/06/2022 (BugFix)
  3344 00003864 88C2                <1> 	mov 	dl, al ; day (BCD)
  3345                              <1> 
  3346                              <1> 	; Set real-time clock date
  3347 00003866 E879000000          <1> 	call	set_rtc_date
  3348                              <1> set_time:
  3349                              <1>         ; Read real-time clock time 
  3350                              <1> 	; (get day light saving time bit status)
  3351 0000386B FA                  <1>  	cli
  3352 0000386C E8CED2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3353                              <1> 	; cf = 1 -> al = 0
  3354 00003871 7207                <1>         jc      short stime1
  3355 00003873 B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3356 00003875 E8AFD2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3357                              <1> stime1:
  3358 0000387A FB                  <1> 	sti
  3359 0000387B 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3360 0000387D 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3361                              <1> 	; DL = 1 or 0 (day light saving time)
  3362                              <1> 	;	
  3363 0000387F A0[F4680000]        <1> 	mov 	al, [hour]
  3364 00003884 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3365 00003886 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3366                              <1> 			     ; AL = AH * 10h + AL
  3367 00003888 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3368 0000388A A0[F5680000]        <1>         mov     al, [minute]
  3369 0000388F D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3370 00003891 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3371                              <1> 			     ; AL = AH * 10h + AL
  3372 00003893 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3373 00003895 A0[F6680000]        <1>         mov     al, [second]
  3374 0000389A D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3375 0000389C D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3376                              <1> 			     ; AL = AH * 10h + AL
  3377 0000389E 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3378                              <1> 
  3379                              <1> 	; Set real-time clock time
  3380                              <1>  	; call	set_rtc_time
  3381                              <1> set_rtc_time:
  3382                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3383                              <1> 	; 15/03/2015
  3384                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3385                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3386                              <1> 	; INT 1Ah
  3387                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3388                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3389                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3390                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3391                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3392                              <1> 	;								:
  3393                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3394                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3395                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3396                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3397                              <1> 	;
  3398                              <1> RTC_30: 				; SET RTC TIME
  3399 000038A0 FA                  <1> 	cli
  3400 000038A1 E899D2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3401 000038A6 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3402 000038A8 E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3403                              <1> RTC_35:
  3404 000038AD 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3405 000038AF B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3406 000038B1 E89D000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3407 000038B6 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3408 000038B8 B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3409 000038BA E894000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3410 000038BF 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3411 000038C1 B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3412 000038C3 E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3413                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3414 000038C8 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3415 000038CC E858D2FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3416 000038D1 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3417 000038D3 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3418 000038D5 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3419 000038D8 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3420 000038DA 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3421 000038DC E872000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3422 000038E1 F8                  <1> 	CLC				; SET CY= 0
  3423 000038E2 FB                  <1> 	sti
  3424 000038E3 C3                  <1> 	RETn				; RETURN WITH CY= 0
  3425                              <1> 
  3426                              <1> set_rtc_date:
  3427                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3428                              <1> 	; 15/03/2015
  3429                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3430                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3431                              <1> 	; INT 1Ah
  3432                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3433                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3434                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3435                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3436                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3437                              <1> 	;
  3438                              <1> RTC_50: 				; SET RTC DATE
  3439 000038E4 FA                  <1> 	cli
  3440 000038E5 E855D2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3441 000038EA 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3442 000038EC E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3443                              <1> RTC_55:
  3444 000038F1 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3445 000038F5 E859000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3446 000038FA 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3447 000038FC B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3448 000038FE E850000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3449 00003903 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3450 00003905 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3451 00003907 E847000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3452 0000390C 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3453 0000390E B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3454 00003910 E83E000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3455 00003915 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3456 00003917 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3457 00003919 E835000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3458                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3459 0000391E 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3460 00003922 E802D2FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3461 00003927 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3462 00003929 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3463 0000392B E823000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3464 00003930 F8                  <1> 	CLC				; SET CY= 0
  3465 00003931 FB                  <1> 	sti
  3466 00003932 C3                  <1> 	RETn				; RETURN CY=0
  3467                              <1> 
  3468                              <1> 	; 15/03/2015
  3469                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3470 00003933 B426                <1> 	mov	ah, 26h
  3471 00003935 B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3472 00003937 E817000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3473 0000393C B482                <1> 	mov	ah, 82h
  3474 0000393E B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3475 00003940 E80E000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3476 00003945 B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3477 00003947 E8DDD1FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3478 0000394C B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3479                              <1> 	;CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3480                              <1> 	;RETn
  3481                              <1> 	; 12/01/2022
  3482 0000394E E9D6D1FFFF          <1> 	jmp	CMOS_READ
  3483                              <1> 
  3484                              <1> 	; 15/03/2015
  3485                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3486                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3487 00003953 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3488                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3489 00003954 D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3490 00003956 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3491 00003957 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3492 00003959 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3493 0000395A E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3494 0000395C 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3495 0000395E E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3496 00003960 B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3497 00003962 D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3498 00003964 E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3499 00003966 90                  <1> 	nop			; I/O DELAY
  3500 00003967 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3501                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3502 00003969 9D                  <1> 	popf	
  3503 0000396A C3                  <1> 	RETn
  3504                              <1> 
  3505                              <1> bf_init:
  3506                              <1> 	; 14/08/2015
  3507                              <1> 	; 02/07/2015
  3508                              <1> 	; 01/07/2015
  3509                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3510                              <1> 	; Buffer (pointer) initialization !
  3511                              <1> 	; 
  3512                              <1> 	; 17/07/2013 - 24/07/2013
  3513                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3514                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3515                              <1> 	;
  3516 0000396B BF[0C6F0000]        <1> 	mov	edi, bufp 
  3517 00003970 B8[047C0000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3518 00003975 29D2                <1> 	sub	edx, edx
  3519 00003977 FECA                <1> 	dec	dl
  3520 00003979 31C9                <1> 	xor	ecx, ecx
  3521 0000397B 49                  <1> 	dec	ecx
  3522                              <1> bi0:
  3523 0000397C 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3524 00003981 AB                  <1> 	stosd
  3525 00003982 89C6                <1> 	mov	esi, eax
  3526 00003984 8916                <1> 	mov	[esi], edx ; 000000FFh
  3527                              <1> 			   ; Not a valid device sign
  3528 00003986 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3529                              <1> 		      ; Not a valid block number sign 	 	
  3530 00003989 3D[D46F0000]        <1> 	cmp	eax, buffer
  3531 0000398E 77EC                <1> 	ja	short bi0
  3532 00003990 B8[047C0000]        <1> 	mov	eax, sb0
  3533 00003995 AB                  <1> 	stosd
  3534 00003996 B8[0C7E0000]        <1> 	mov	eax, sb1
  3535 0000399B AB                  <1> 	stosd
  3536 0000399C 89C6                <1> 	mov	esi, eax ; offset sb1
  3537 0000399E 8916                <1> 	mov	[esi], edx ; 000000FFh
  3538                              <1> 			   ; Not a valid device sign
  3539 000039A0 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3540                              <1> 		      ; Not a valid block number sign 	 
  3541                              <1> 	; 14/08/2015
  3542                              <1> 	;call 	rdev_init
  3543                              <1> 	;retn
  3544                              <1> 
  3545                              <1> rdev_init: ; root device, super block buffer initialization
  3546                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3547                              <1> 	; 14/08/2015
  3548                              <1> 	; Retro UNIX 386 v1 feature only !
  3549                              <1> 	;
  3550                              <1> 	; NOTE: Disk partitions (file systems), logical
  3551                              <1> 	; drive initialization, partition's start sector etc.
  3552                              <1> 	; will be coded here, later in 'ldrv_init'	
  3553                              <1> 
  3554 000039A3 0FB605[7A660000]    <1> 	movzx	eax, byte [boot_drv]
  3555                              <1> rdi_0:
  3556 000039AA 3C80                <1> 	cmp	al, 80h
  3557 000039AC 7202                <1> 	jb	short rdi_1
  3558 000039AE 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3559                              <1> rdi_1:
  3560 000039B0 A2[306F0000]        <1> 	mov	[rdev], al
  3561 000039B5 BB[047C0000]        <1>         mov	ebx, sb0 ; super block buffer
  3562 000039BA 8903                <1> 	mov 	[ebx], eax
  3563 000039BC B001                <1> 	mov	al, 1 ; eax = 1
  3564 000039BE 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3565                              <1> 	;call 	diskio
  3566                              <1> 	;retn
  3567                              <1> 	; 24/12/2021
  3568 000039C1 E934250000          <1> 	jmp	diskio
  3569                              <1> 
  3570                              <1> ; 23/10/2015
  3571                              <1> com1_irq4:
  3572 000039C6 [CE390000]          <1> 	dd	dummy_retn
  3573                              <1> com2_irq3:
  3574 000039CA [CE390000]          <1> 	dd	dummy_retn
  3575                              <1> 
  3576                              <1> dummy_retn:
  3577 000039CE C3                  <1> 	retn
  2100                                  %include 'u1.s'        ; 10/05/2015
  2101                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS1.INC
  2102                              <1> ; Last Modification: 27/02/2022
  2103                              <1> ; ----------------------------------------------------------------------------
  2104                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2105                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2106                              <1> ;
  2107                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2108                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2109                              <1> ; <Bell Laboratories (17/3/1972)>
  2110                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2111                              <1> ;
  2112                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2113                              <1> ;
  2114                              <1> ; ****************************************************************************
  2115                              <1> 
  2116                              <1> unkni: ; / used for all system calls
  2117                              <1> sysent: ; < enter to system call >
  2118                              <1> 	; 08/01/2022
  2119                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2120                              <1> 	; 19/10/2015
  2121                              <1> 	; 21/09/2015
  2122                              <1> 	; 01/07/2015
  2123                              <1> 	; 19/05/2015
  2124                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2125                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2126                              <1> 	;
  2127                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2128                              <1> 	; The trap type is determined and an indirect jump is made to 
  2129                              <1> 	; the appropriate system call handler. If there is a trap inside
  2130                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2131                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2132                              <1> 	; instructor is decoded to get the the system code part (see
  2133                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2134                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2135                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2136                              <1> 	; is called. If the call is legitimate control passes to the
  2137                              <1> 	; appropriate system routine.
  2138                              <1> 	;
  2139                              <1> 	; Calling sequence:
  2140                              <1> 	;	Through a trap caused by any sys call outside the system.
  2141                              <1> 	; Arguments:
  2142                              <1> 	;	Arguments of particular system call.	
  2143                              <1> 	; ...............................................................
  2144                              <1> 	;	
  2145                              <1> 	; Retro UNIX 8086 v1 modification: 
  2146                              <1> 	;       System call number is in EAX register.
  2147                              <1> 	;
  2148                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2149                              <1> 	;	registers depending of function details.
  2150                              <1>   	;
  2151                              <1> 	; 16/04/2015
  2152 000039CF 368925[446F0000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2153                              <1> 	; save user registers
  2154 000039D6 1E                  <1> 	push	ds
  2155 000039D7 06                  <1> 	push	es
  2156 000039D8 0FA0                <1> 	push	fs
  2157 000039DA 0FA8                <1> 	push	gs
  2158 000039DC 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2159                              <1> 	;
  2160                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2161                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2162                              <1> 	;	for saving/restoring user registers.)
  2163                              <1> 	;
  2164 000039DD 50                  <1> 	push	eax ; 01/07/2015
  2165 000039DE 66B81000            <1> 	mov     ax, KDATA
  2166 000039E2 8ED8                <1>         mov     ds, ax
  2167 000039E4 8EC0                <1>         mov     es, ax
  2168 000039E6 8EE0                <1>         mov     fs, ax
  2169 000039E8 8EE8                <1>         mov     gs, ax
  2170 000039EA A1[886B0000]        <1> 	mov	eax, [k_page_dir]
  2171 000039EF 0F22D8              <1> 	mov	cr3, eax
  2172 000039F2 58                  <1> 	pop	eax ; 01/07/2015
  2173                              <1> 	; 19/10/2015
  2174 000039F3 FC                  <1> 	cld
  2175                              <1> 	;
  2176 000039F4 FE05[416F0000]      <1> 	inc	byte [sysflg]
  2177                              <1> 		; incb sysflg / indicate a system routine is in progress
  2178 000039FA FB                  <1>         sti 	; 18/01/2014
  2179                              <1> 	;jnz	panic ; 24/05/2013
  2180                              <1> 	; 24/12/2021
  2181 000039FB 7405                <1> 	jz	short _1
  2182 000039FD E984F9FFFF          <1> 	jmp	panic
  2183                              <1> 		; beq 1f
  2184                              <1> 		; jmp panic ; / called if trap inside system
  2185                              <1> ;1:
  2186                              <1> _1:	; 24/12/2021
  2187                              <1> 	; 16/04/2015
  2188 00003A02 A3[4C6F0000]        <1> 	mov	[u.r0], eax
  2189 00003A07 8925[486F0000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2190                              <1> 	;
  2191                              <1> 		; mov $s.syst+2,clockp
  2192                              <1> 		; mov r0,-(sp) / save user registers 
  2193                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2194                              <1> 			   ; / in u.r0
  2195                              <1> 		; mov r1,-(sp)
  2196                              <1> 		; mov r2,-(sp)
  2197                              <1> 		; mov r3,-(sp)
  2198                              <1> 		; mov r4,-(sp)
  2199                              <1> 		; mov r5,-(sp)
  2200                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2201                              <1> 		             ; / arithmetic unit
  2202                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2203                              <1> 		             ; / extended arithmetic unit
  2204                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2205                              <1> 		             ; / arithmetic unit
  2206                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2207                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2208                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2209                              <1> 		; sub $sys,r0 / get xxx code
  2210 00003A0D C1E002              <1> 	shl	eax, 2
  2211                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2212 00003A10 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2213                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2214                              <1> 	;jnb	short badsys
  2215                              <1> 		; bhis badsys / yes, bad system call
  2216                              <1> 	; 08/01/2022
  2217 00003A15 7205                <1> 	jb	short _2
  2218 00003A17 E95D010000          <1> 	jmp	badsys
  2219                              <1> _2:
  2220                              <1> 	; 08/01/2022
  2221                              <1> 	;cmc
  2222                              <1> 	;pushf	
  2223                              <1> 	;push	eax
  2224 00003A1C 8B2D[446F0000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2225                              <1> 	;mov	al, 0FEh ; 11111110b
  2226                              <1> 	;;adc	al, 0 ; al = al + cf
  2227                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2228 00003A22 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2229                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2230                              <1> 				 ; / and clear carry bit
  2231                              <1> 	;pop	ebp ; eax
  2232 00003A26 89C5                <1> 	mov	ebp, eax ; 25/12/2021
  2233                              <1> 	;popf
  2234                              <1>         ;;jc	badsys
  2235                              <1> 	; 24/12/2021
  2236                              <1> 	;jnc	short _3  ; 08/01/2022
  2237                              <1> 	;jmp	badsys
  2238                              <1> ;_3:
  2239 00003A28 A1[4C6F0000]        <1> 	mov	eax, [u.r0]
  2240                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2241 00003A2D FFA5[333A0000]      <1> 	jmp	dword [ebp+syscalls]
  2242                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2243                              <1> 		            ; / to proper system routine.
  2244                              <1> syscalls: ; 1:
  2245                              <1> 	; 21/09/2015
  2246                              <1> 	; 01/07/2015
  2247                              <1> 	; 16/04/2015 (32 bit address modification) 
  2248 00003A33 [433B0000]          <1> 	dd sysrele	; / 0
  2249 00003A37 [EB3B0000]          <1> 	dd sysexit 	; / 1
  2250 00003A3B [163D0000]          <1> 	dd sysfork 	; / 2
  2251 00003A3F [1C3E0000]          <1> 	dd sysread 	; / 3
  2252 00003A43 [2F3E0000]          <1> 	dd syswrite 	; / 4
  2253 00003A47 [983E0000]          <1> 	dd sysopen 	; / 5
  2254 00003A4B [C33F0000]          <1> 	dd sysclose 	; / 6
  2255 00003A4F [913C0000]          <1> 	dd syswait 	; / 7
  2256 00003A53 [403F0000]          <1> 	dd syscreat 	; / 8
  2257 00003A57 [7C430000]          <1> 	dd syslink 	; / 9
  2258 00003A5B [38440000]          <1> 	dd sysunlink 	; / 10
  2259 00003A5F [02450000]          <1> 	dd sysexec 	; / 11
  2260 00003A63 [854B0000]          <1> 	dd syschdir 	; / 12
  2261 00003A67 [684C0000]          <1> 	dd systime 	; / 13
  2262 00003A6B [7C3F0000]          <1> 	dd sysmkdir 	; / 14
  2263 00003A6F [D54B0000]          <1> 	dd syschmod 	; / 15
  2264 00003A73 [384C0000]          <1> 	dd syschown 	; / 16
  2265 00003A77 [9B4C0000]          <1> 	dd sysbreak 	; / 17
  2266 00003A7B [C2480000]          <1> 	dd sysstat 	; / 18
  2267 00003A7F [6B4D0000]          <1> 	dd sysseek 	; / 19
  2268 00003A83 [7D4D0000]          <1> 	dd systell 	; / 20
  2269 00003A87 [3C580000]          <1> 	dd sysmount 	; / 21
  2270 00003A8B [27590000]          <1> 	dd sysumount 	; / 22
  2271 00003A8F [F94D0000]          <1> 	dd syssetuid 	; / 23
  2272 00003A93 [2A4E0000]          <1> 	dd sysgetuid 	; / 24
  2273 00003A97 [774C0000]          <1> 	dd sysstime 	; / 25
  2274 00003A9B [ED4D0000]          <1> 	dd sysquit 	; / 26
  2275 00003A9F [E14D0000]          <1> 	dd sysintr 	; / 27
  2276 00003AA3 [9F480000]          <1> 	dd sysfstat 	; / 28
  2277 00003AA7 [E03F0000]          <1> 	dd sysemt 	; / 29
  2278 00003AAB [2C400000]          <1> 	dd sysmdate 	; / 30
  2279 00003AAF [86400000]          <1> 	dd sysstty 	; / 31
  2280 00003AB3 [6F420000]          <1> 	dd sysgtty 	; / 32
  2281 00003AB7 [27400000]          <1> 	dd sysilgins 	; / 33
  2282 00003ABB [B3610000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2283                              <1> 			     ; 11/06/2014
  2284 00003ABF [CA610000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2285                              <1> 			     ; 01/07/2015
  2286 00003AC3 [A2620000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2287                              <1> 			     ; 21/09/2015 - get last error number
  2288                              <1> end_of_syscalls:
  2289                              <1> 
  2290                              <1> error:
  2291                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2292                              <1> 	; 17/09/2015
  2293                              <1> 	; 03/09/2015
  2294                              <1> 	; 01/09/2015
  2295                              <1> 	; 09/06/2015
  2296                              <1> 	; 13/05/2015
  2297                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2298                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2299                              <1> 	;
  2300                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2301                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2302                              <1> 	;
  2303                              <1> 	; INPUTS -> none
  2304                              <1> 	; OUTPUTS ->
  2305                              <1> 	;	processor status - carry (c) bit is set (means error)
  2306                              <1> 	;
  2307                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2308                              <1> 	; 	      Because, jumps to error procedure
  2309                              <1> 	;	      disrupts push-pop nesting balance)
  2310                              <1> 	;
  2311 00003AC7 8B2D[446F0000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2312 00003ACD 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2313                              <1> 				 ; (system call will return with cf = 1)
  2314                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2315                              <1> 		               ; / users stack
  2316                              <1> 	; 17/09/2015
  2317 00003AD1 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2318                              <1> 				 ; for saving/restoring user registers	
  2319                              <1> 	;cmp	ebp, [u.usp]
  2320                              <1> 	;je	short err0	
  2321 00003AD4 892D[486F0000]      <1> 	mov	[u.usp], ebp
  2322                              <1> ;err0:
  2323                              <1> 	; 01/09/2015
  2324 00003ADA 8B25[486F0000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2325                              <1> 				    ; 10/04/2013
  2326                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2327                              <1> 				    ; related procedures will jump to 'error'
  2328                              <1> 				    ; procedure directly without returning to 
  2329                              <1> 				    ; the caller procedure. So, stack pointer
  2330                              <1>                                     ; must be restored here.)
  2331                              <1> 	; 13/05/2015
  2332                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2333                              <1> 	;	'get last error' system call later. 	
  2334                              <1> 
  2335                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2336 00003AE0 C605[B36F0000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2337                              <1> 
  2338                              <1> sysret: ; < return from system call>
  2339                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2340                              <1> 	; 10/09/2015
  2341                              <1> 	; 29/07/2015
  2342                              <1> 	; 25/06/2015
  2343                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2344                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2345                              <1> 	;
  2346                              <1> 	; 'sysret' first checks to see if process is about to be 
  2347                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2348                              <1> 	; If not, following happens:	 
  2349                              <1> 	; 	1) The user's stack pointer is restored.
  2350                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2351                              <1> 	;	   i-node has been modified. If it has, it is written out
  2352                              <1> 	;	   via 'ppoke'.
  2353                              <1> 	;	3) If the super block has been modified, it is written out
  2354                              <1> 	;	   via 'ppoke'.				
  2355                              <1> 	;	4) If the dismountable file system's super block has been
  2356                              <1> 	;	   modified, it is written out to the specified device
  2357                              <1> 	;	   via 'ppoke'.
  2358                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2359                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2360                              <1> 	;	   another user a chance to run.
  2361                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2362                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2363                              <1> 	;
  2364                              <1> 	; Calling sequence:
  2365                              <1> 	;	jump table or 'br sysret'
  2366                              <1> 	; Arguments: 
  2367                              <1> 	;	-	
  2368                              <1> 	; ...............................................................
  2369                              <1> 	;	
  2370                              <1> 	; ((AX=r1 for 'iget' input))
  2371                              <1> 	;	
  2372                              <1> 	;xor	ax, ax ; 04/05/2013
  2373                              <1> 	; 24/12/2021
  2374 00003AE7 31C0                <1> 	xor	eax, eax
  2375                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2376 00003AE9 FEC0                <1> 	inc	al ; 04/05/2013
  2377 00003AEB 3805[9A6F0000]      <1> 	cmp	[u.bsys], al ; 1
  2378                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2379                              <1> 	;jnb	sysexit ; 04/05/2013
  2380                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2381                              <1> 	; 24/12/2021
  2382 00003AF1 720F                <1> 	jb	short _3
  2383 00003AF3 C705[A16F0000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2383 00003AFB 0000                <1>
  2384 00003AFD E9E9000000          <1> 	jmp	sysexit
  2385                              <1> _3:
  2386                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2387                              <1> 		; mov u.sp,sp / no point stack to users stack
  2388 00003B02 FEC8                <1> 	dec 	al ; mov ax, 0
  2389                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2390 00003B04 E8DB160000          <1> 	call	iget
  2391                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2392                              <1> 		            ; / it is written out
  2393                              <1> 	;xor 	ax, ax ; 0
  2394                              <1> 	; 24/12/2021
  2395 00003B09 31C0                <1> 	xor	eax, eax
  2396 00003B0B 3805[3F6F0000]      <1> 	cmp	[smod], al ; 0
  2397                              <1> 		; tstb	smod / has the super block been modified
  2398 00003B11 7614                <1> 	jna	short sysret1
  2399                              <1> 		; beq	1f / no, 1f
  2400 00003B13 A2[3F6F0000]        <1> 	mov	[smod], al ; 0
  2401                              <1> 		; clrb smod / yes, clear smod
  2402 00003B18 BB[047C0000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2403 00003B1D 66810B0002          <1>    	or	word [ebx], 200h ;;
  2404                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2405                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2406                              <1> 		      	      ; / output
  2407                              <1> 	; AX = 0
  2408 00003B22 E8BB220000          <1> 	call 	poke ; 07/08/2013
  2409                              <1> 	; call	ppoke
  2410                              <1> 	; AX = 0
  2411                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2412                              <1> sysret1: ;1:
  2413 00003B27 3805[406F0000]      <1> 	cmp	[mmod], al ; 0
  2414                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2415                              <1> 		           ; / system
  2416 00003B2D 7614                <1> 	jna	short sysrel0
  2417                              <1> 		; beq 1f / been modified?  no, 1f
  2418 00003B2F A2[406F0000]        <1> 	mov	[mmod], al ; 0	
  2419                              <1> 		; clrb	mmod / yes, clear mmod
  2420                              <1>         ;mov    ax, [mntd]
  2421                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2422 00003B34 BB[0C7E0000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2423                              <1>         ;;mov	[ebx], al
  2424                              <1> 	;mov    [sb1], al
  2425                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2426 00003B39 66810B0002          <1> 	or	word [ebx], 200h
  2427                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2428                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2429 00003B3E E89F220000          <1> 	call	poke ; 07/08/2013
  2430                              <1> 	;call	ppoke 
  2431                              <1> 		; jsr r0,ppoke / write it out to its device
  2432                              <1>         ;xor    al, al ; 26/04/2013       
  2433                              <1> ;1:
  2434                              <1> 		; tstb uquant / is the time quantum 0?
  2435                              <1> 		; bne 1f / no, don't swap it out
  2436                              <1> 
  2437                              <1> sysrele: ; < release >
  2438                              <1> 	; 14/10/2015
  2439                              <1> 	; 01/09/2015
  2440                              <1> 	; 24/07/2015
  2441                              <1> 	; 14/05/2015
  2442                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2443                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2444                              <1> 	;
  2445                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2446                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2447                              <1> 	; turns off the system flag. It then checked to see if there is
  2448                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2449                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2450                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2451                              <1> 	; the user, a rti is made.
  2452                              <1> 	;
  2453                              <1> 	; Calling sequence:
  2454                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2455                              <1> 	; Arguments:
  2456                              <1> 	;	-	
  2457                              <1> 	; ...............................................................
  2458                              <1> 	;	
  2459                              <1> 	; 23/02/2014 (swapret)
  2460                              <1> 	; 22/09/2013
  2461                              <1> sysrel0: ;1:
  2462 00003B43 803D[8E6F0000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2463                              <1> 		; tstb uquant / is the time quantum 0?
  2464 00003B4A 7705                <1>         ja      short swapret
  2465                              <1> 		; bne 1f / no, don't swap it out
  2466                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2467 00003B4C E829130000          <1> 	call	tswap
  2468                              <1> 		; jsr r0,tswap / yes, swap it out
  2469                              <1> ;
  2470                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2471                              <1> swapret: ;1:
  2472                              <1> 	; 10/09/2015
  2473                              <1> 	; 01/09/2015
  2474                              <1> 	; 14/05/2015
  2475                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2476                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2477                              <1> 	; cli
  2478                              <1> 	; 24/07/2015
  2479                              <1> 	;
  2480                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2481                              <1> 	;; mov	esp, [u.usp]
  2482                              <1> 
  2483                              <1> 	; 22/09/2013
  2484 00003B51 E8FB140000          <1> 	call	isintr
  2485                              <1> 	; 20/10/2013
  2486 00003B56 7405                <1> 	jz	short sysrel1
  2487 00003B58 E877000000          <1> 	call	intract
  2488                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2489                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2490                              <1> 		               ; / action
  2491                              <1> sysrel1:
  2492 00003B5D FA                  <1> 	cli ; 14/10/2015
  2493 00003B5E FE0D[416F0000]      <1> 	dec	byte [sysflg]
  2494                              <1> 		; decb sysflg / turn system flag off
  2495 00003B64 A1[A56F0000]        <1> 	mov     eax, [u.pgdir]
  2496 00003B69 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2497                              <1> 			  ; (others are different than kernel page tables) 
  2498                              <1> 	; 10/09/2015
  2499 00003B6C 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2500                              <1> 		; mov (sp)+,sc / restore user registers
  2501                              <1> 		; mov (sp)+,mq
  2502                              <1> 		; mov (sp)+,ac
  2503                              <1> 		; mov (sp)+,r5
  2504                              <1> 		; mov (sp)+,r4
  2505                              <1> 		; mov (sp)+,r3
  2506                              <1> 		; mov (sp)+,r2
  2507                              <1> 	;
  2508 00003B6D A1[4C6F0000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2509 00003B72 0FA9                <1> 	pop	gs
  2510 00003B74 0FA1                <1> 	pop	fs
  2511 00003B76 07                  <1> 	pop	es
  2512 00003B77 1F                  <1> 	pop	ds
  2513 00003B78 CF                  <1> 	iretd	
  2514                              <1> 		; rti / no, return from interrupt
  2515                              <1> 
  2516                              <1> badsys:
  2517                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2518                              <1> 	; (Major Modification: 'core' dumping procedure in
  2519                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2520                              <1> 	;	has been changed to print 'Invalid System Call !'
  2521                              <1> 	;	message on the user's console tty.)
  2522                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2523                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2524                              <1> 	; (EAX = Function number)  
  2525                              <1> 	;
  2526 00003B79 FE05[9A6F0000]      <1> 	inc	byte [u.bsys]
  2527                              <1> 	;
  2528 00003B7F 8B1D[446F0000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2529 00003B85 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2530 00003B87 E86BDBFFFF          <1> 	call	dwordtohex
  2531 00003B8C 8915[E4680000]      <1> 	mov	[bsys_msg_eip], edx
  2532 00003B92 A3[E8680000]        <1> 	mov	[bsys_msg_eip+4], eax
  2533 00003B97 A1[4C6F0000]        <1> 	mov	eax, [u.r0]
  2534 00003B9C E856DBFFFF          <1> 	call	dwordtohex
  2535 00003BA1 8915[D4680000]      <1> 	mov	[bsys_msg_eax], edx
  2536 00003BA7 A3[D8680000]        <1> 	mov	[bsys_msg_eax+4], eax
  2537                              <1> 	; 24/12/2021
  2538                              <1> 	;xor	eax, eax
  2539                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2540                              <1> 	;mov	ebx, [u.fofp]
  2541                              <1> 	;mov	[ebx], eax
  2542                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2543                              <1> 	;inc	eax
  2544                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2545                              <1> 		; writei
  2546                              <1> 		; INPUTS ->
  2547                              <1> 		;    r1 - inode number
  2548                              <1> 		;    u.count - byte count to be written
  2549                              <1> 		;    u.base - points to user buffer
  2550                              <1> 		;    u.fofp - points to word with current file offset
  2551                              <1> 		; OUTPUTS ->
  2552                              <1> 		;    u.count - cleared
  2553                              <1> 		;    u.nread - accumulates total bytes passed back	
  2554                              <1> 		;
  2555                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2556                              <1> 	;call	writei
  2557                              <1> 	;;mov	eax, 1
  2558                              <1> 	;jmp	sysexit
  2559                              <1> 
  2560                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  2561 00003BAC BE[B5680000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2562 00003BB1 0FB61D[9B6F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2563 00003BB8 8A83[A76C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2564 00003BBE C605[B76B0000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2565 00003BC5 A2[A06F0000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2566 00003BCA E8B8260000          <1> 	call	print_cmsg
  2567                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2568 00003BCF E9F3FEFFFF          <1> 	jmp	error
  2569                              <1> 
  2570                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2571                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2572                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2573                              <1> 		; br 1f / error
  2574                              <1> 		; neg r1 / negate the i-number to open the core image file
  2575                              <1> 		       ; / for writing
  2576                              <1> 		; jsr r0,iopen / open the core image file
  2577                              <1> 		; jsr r0,itrunc / free all associated blocks
  2578                              <1> 		; br 2f
  2579                              <1> ;1:
  2580                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2581                              <1> 		; jsr r0,maknod / make an i-node
  2582                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2583                              <1> ;2:
  2584                              <1> 		; mov $core,u.base / move address core to u.base
  2585                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2586                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2587                              <1> 		; clr u.off / clear user offset
  2588                              <1> 		; jsr r0,writei / write out the core image to the user
  2589                              <1> 		; mov $user,u.base / pt. u.base to user
  2590                              <1> 		; mov $64.,u.count / u.count = 64
  2591                              <1> 		; jsr r0,writei / write out all the user parameters
  2592                              <1> 		; neg r1 / make i-number positive
  2593                              <1> 		; jsr r0,iclose / close the core image file
  2594                              <1> 		; br sysexit /
  2595                              <1> ;3:
  2596                              <1> 		; <core\0\0>
  2597                              <1> 
  2598                              <1> intract: ; / interrupt action
  2599                              <1> 	; 14/10/2015
  2600                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2601                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2602                              <1> 	;
  2603                              <1> 	; Retro UNIX 8086 v1 modification !
  2604                              <1> 	; (Process/task switching and quit routine by using
  2605                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2606                              <1> 	;
  2607                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2608                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2609                              <1> 	;		'intract' will jump to 'sysexit'.
  2610                              <1> 	;	    Intract will return to the caller 
  2611                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2612                              <1> 	; 14/10/2015
  2613 00003BD4 FB                  <1> 	sti
  2614                              <1> 	; 07/12/2013	
  2615 00003BD5 66FF05[926F0000]    <1> 	inc 	word [u.quit]
  2616 00003BDC 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2617 00003BDE 66FF0D[926F0000]    <1> 	dec	word [u.quit]
  2618                              <1> 	; 16/04/2015
  2619 00003BE5 C3                  <1> 	retn
  2620                              <1> intrct0:	
  2621 00003BE6 58                  <1> 	pop	eax ; call intract -> retn
  2622                              <1> 	;
  2623 00003BE7 31C0                <1> 	xor 	eax, eax
  2624 00003BE9 FEC0                <1> 	inc	al  ; mov ax, 1
  2625                              <1> ;;;
  2626                              <1> 	; UNIX v1 original 'intract' routine... 
  2627                              <1> 	; / interrupt action
  2628                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2629                              <1> 		; bne 1f / no, 1f
  2630                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2631                              <1> 	; 1: / now in user area
  2632                              <1> 		; mov r1,-(sp) / save r1
  2633                              <1> 		; mov u.ttyp,r1 
  2634                              <1> 			; / pointer to tty buffer in control-to r1
  2635                              <1> 		; cmpb 6(r1),$177
  2636                              <1> 			; / is the interrupt char equal to "del"
  2637                              <1> 		; beq 1f / yes, 1f
  2638                              <1> 		; clrb 6(r1) 
  2639                              <1> 		        ; / no, clear the byte 
  2640                              <1> 			; / (must be a quit character)
  2641                              <1> 		; mov (sp)+,r1 / restore r1
  2642                              <1> 		; clr u.quit / clear quit flag
  2643                              <1> 		; bis $20,2(sp) 
  2644                              <1> 		    	; / set trace for quit (sets t bit of 
  2645                              <1> 			; / ps-trace trap)
  2646                              <1> 		; rti   ;  / return from interrupt
  2647                              <1> 	; 1: / interrupt char = del
  2648                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2649                              <1> 			   ; / in the buffer
  2650                              <1> 		; mov (sp)+,r1 / restore r1
  2651                              <1> 		; cmp u.intr,$core / should control be 
  2652                              <1> 				; / transferred to loc core?
  2653                              <1> 		; blo 1f
  2654                              <1> 		; jmp *u.intr / user to do rti yes, 
  2655                              <1> 				; / transfer to loc core
  2656                              <1> 	; 1:
  2657                              <1> 		; sys 1 / exit
  2658                              <1> 
  2659                              <1> sysexit: ; <terminate process>
  2660                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2661                              <1> 	; 01/09/2015
  2662                              <1> 	; 31/08/2015
  2663                              <1> 	; 14/05/2015
  2664                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2665                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2666                              <1> 	;
  2667                              <1> 	; 'sysexit' terminates a process. First each file that
  2668                              <1> 	; the process has opened is closed by 'flose'. The process
  2669                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2670                              <1> 	; searched to find children of the dying process. If any of
  2671                              <1> 	; children are zombies (died by not waited for), they are
  2672                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2673                              <1> 	; dying process's parent. When the parent is found, it is
  2674                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2675                              <1> 	; one of these, the dying process just dies. If it is waiting
  2676                              <1> 	; for a child process to die, it notified that it doesn't 
  2677                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2678                              <1> 	; (waiting to active). It is awakened and put on runq by
  2679                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2680                              <1> 	; it will never be run again but stays around until a 'wait'
  2681                              <1> 	; is completed by it's parent process. If the parent is not
  2682                              <1> 	; found, process just dies. This means 'swap' is called with
  2683                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2684                              <1> 	; to write out the process and 'rswap' reads the new process
  2685                              <1> 	; over the one that dies..i.e., the dying process is 
  2686                              <1> 	; overwritten and destroyed.	
  2687                              <1>  	;
  2688                              <1> 	; Calling sequence:
  2689                              <1> 	;	sysexit or conditional branch.
  2690                              <1> 	; Arguments:
  2691                              <1> 	;	-	
  2692                              <1> 	; ...............................................................
  2693                              <1> 	;	
  2694                              <1> 	; Retro UNIX 8086 v1 modification: 
  2695                              <1> 	;       System call number (=1) is in EAX register.
  2696                              <1> 	;
  2697                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2698                              <1> 	;       registers depending of function details.
  2699                              <1> 	;
  2700                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2701                              <1> 	;
  2702                              <1> ; / terminate process
  2703                              <1> 	; AX = 1
  2704                              <1> 	;dec 	ax ; 0
  2705                              <1> 	; 24/12/2021
  2706 00003BEB 48                  <1> 	dec	eax ; 0
  2707                              <1> 	;dec 	ax ; 0
  2708 00003BEC 66A3[906F0000]      <1> 	mov	[u.intr], ax ; 0
  2709                              <1> 		; clr u.intr / clear interrupt control word
  2710                              <1> 		; clr r1 / clear r1
  2711                              <1> 	; AX = 0
  2712                              <1> sysexit_1: ; 1:
  2713                              <1> 	; AX = File descriptor
  2714                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2715                              <1> 		; / Search the whole list
  2716 00003BF2 E8690D0000          <1> 	call	fclose
  2717                              <1> 		; jsr r0,fclose / close all files the process opened
  2718                              <1> 	;; ignore error return
  2719                              <1> 		; br .+2 / ignore error return
  2720                              <1> 	;inc	ax
  2721 00003BF7 FEC0                <1> 	inc	al
  2722                              <1> 		; inc r1 / increment file descriptor
  2723                              <1> 	;cmp	ax, 10
  2724 00003BF9 3C0A                <1> 	cmp	al, 10
  2725                              <1> 		; cmp r1,$10. / end of u.fp list?
  2726 00003BFB 72F5                <1> 	jb	short sysexit_1
  2727                              <1> 		; blt 1b / no, go back
  2728 00003BFD 0FB61D[9B6F0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2729                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2730 00003C04 88A3[C76C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2731                              <1> 		; clrb p.stat-1(r1) / free the process
  2732                              <1> 	;shl	bx, 1
  2733 00003C0A D0E3                <1> 	shl	bl, 1
  2734                              <1> 		; asl r1 / use r1 for index into the below tables
  2735 00003C0C 668B8B[666C0000]    <1> 	mov	cx, [ebx+p.pid-2]
  2736                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2737 00003C13 668B93[866C0000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2738                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2739                              <1> 	; xor 	bx, bx ; 0
  2740 00003C1A 30DB                <1> 	xor	bl, bl ; 0
  2741                              <1> 		; clr r2
  2742 00003C1C 31F6                <1> 	xor	esi, esi ; 0
  2743                              <1> 		; clr r5 / initialize reg
  2744                              <1> sysexit_2: ; 1:
  2745                              <1> 	        ; / find children of this dying process, 
  2746                              <1> 		; / if they are zombies, free them
  2747                              <1> 	;add	bx, 2
  2748 00003C1E 80C302              <1> 	add	bl, 2
  2749                              <1> 		; add $2,r2 / search parent process table 
  2750                              <1> 		          ; / for dying process's name
  2751 00003C21 66398B[866C0000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2752                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2753 00003C28 7513                <1> 	jne	short sysexit_4
  2754                              <1> 		; bne 3f / no
  2755                              <1> 	;shr	bx, 1
  2756 00003C2A D0EB                <1> 	shr	bl, 1
  2757                              <1> 		; asr r2 / yes, it is a parent
  2758 00003C2C 80BB[C76C0000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2759                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2760                              <1> 				     ; / dying process a zombie
  2761 00003C33 7506                <1> 	jne	short sysexit_3 
  2762                              <1> 		; bne 2f / no
  2763 00003C35 88A3[C76C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2764                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2765                              <1> sysexit_3: ; 2:
  2766                              <1> 	;shr	bx, 1
  2767 00003C3B D0E3                <1> 	shl	bl, 1
  2768                              <1> 		; asl r2
  2769                              <1> sysexit_4: ; 3:
  2770                              <1> 		; / search the process name table 
  2771                              <1> 		; / for the dying process's parent
  2772 00003C3D 663993[666C0000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2773                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2774 00003C44 7502                <1> 	jne	short sysexit_5
  2775                              <1> 		; bne 3f / no
  2776 00003C46 89DE                <1> 	mov	esi, ebx
  2777                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2778                              <1> 		          ; / process # x2) in r5
  2779                              <1> sysexit_5: ; 3:
  2780                              <1> 	;cmp	bx, nproc + nproc
  2781 00003C48 80FB20              <1> 	cmp	bl, nproc + nproc
  2782                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2783 00003C4B 72D1                <1> 	jb	short sysexit_2
  2784                              <1> 		; blt 1b / no, go back
  2785                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2786 00003C4D 21F6                <1> 	and	esi, esi ; r5=r1
  2787 00003C4F 7431                <1> 	jz	short sysexit_6
  2788                              <1> 		; beq 2f / no parent has been found. 
  2789                              <1> 		       ; / The process just dies
  2790 00003C51 66D1EE              <1> 	shr	si, 1
  2791                              <1> 		; asr r1 / set up index to p.stat
  2792 00003C54 8A86[C76C0000]      <1> 	mov	al, [esi+p.stat-1]
  2793                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2794 00003C5A 20C0                <1> 	and	al, al
  2795 00003C5C 7424                <1> 	jz	short sysexit_6
  2796                              <1> 		; beq 2f / if its been freed, 2f
  2797 00003C5E 3C03                <1> 	cmp	al, 3
  2798                              <1> 		; cmp r2,$3 / is parent a zombie?
  2799 00003C60 7420                <1> 	je	short sysexit_6
  2800                              <1> 		; beq 2f / yes, 2f
  2801                              <1> 	; BH = 0
  2802 00003C62 8A1D[9B6F0000]      <1> 	mov	bl, [u.uno]
  2803                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2804 00003C68 C683[C76C0000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2805                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2806                              <1> 	; 05/02/2014
  2807 00003C6F 3C01                <1> 	cmp	al, 1 ; SRUN
  2808 00003C71 740F                <1> 	je	short sysexit_6
  2809                              <1> 	;cmp	al, 2
  2810                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2811                              <1> 			  ; / this child to die
  2812                              <1> 	;jne	short sysexit_6	
  2813                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2814                              <1> 	; 05/02/2014
  2815                              <1> 	; p.stat = 2 --> waiting
  2816                              <1> 	; p.stat = 4 --> sleeping
  2817 00003C73 C686[C76C0000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2818                              <1> 	;dec	byte [esi+p.stat-1]
  2819                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2820 00003C7A 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2821                              <1> 	; 
  2822                              <1> 	;mov	ebx, runq + 4
  2823                              <1> 		; mov $runq+4,r2 / on the runq
  2824 00003C7D E8CF120000          <1> 	call	putlu
  2825                              <1> 		; jsr r0, putlu
  2826                              <1> sysexit_6: ; 2:
  2827                              <1> 	; 31/08/2015
  2828                              <1> 		; / the process dies
  2829 00003C82 C605[9B6F0000]00    <1> 	mov	byte [u.uno], 0
  2830                              <1> 		; clrb u.uno / put zero as the process number, 
  2831                              <1> 	           ; / so "swap" will
  2832 00003C89 E8F6110000          <1> 	call	swap
  2833                              <1> 		; jsr r0,swap / overwrite process with another process
  2834                              <1> hlt_sys:
  2835                              <1> 	;sti ; 18/01/2014
  2836                              <1> hlts0:
  2837 00003C8E F4                  <1> 	hlt
  2838 00003C8F EBFD                <1> 	jmp	short hlts0
  2839                              <1> 		; 0 / and thereby kill it; halt?
  2840                              <1> 
  2841                              <1> 
  2842                              <1> syswait: ; < wait for a processs to die >
  2843                              <1> 	; 09/02/2022
  2844                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2845                              <1> 	; 17/09/2015
  2846                              <1> 	; 02/09/2015
  2847                              <1> 	; 01/09/2015
  2848                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2849                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2850                              <1> 	;
  2851                              <1> 	; 'syswait' waits for a process die. 
  2852                              <1> 	; It works in following way:
  2853                              <1> 	;    1) From the parent process number, the parent's 
  2854                              <1> 	; 	process name is found. The p.ppid table of parent
  2855                              <1> 	;	names is then searched for this process name.
  2856                              <1> 	;	If a match occurs, r2 contains child's process
  2857                              <1> 	;	number. The child status is checked to see if it is
  2858                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2859                              <1> 	;	If it is, the child process is freed and it's name
  2860                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2861                              <1> 	;	If the child is not a zombie, nothing happens and
  2862                              <1> 	;	the search goes on through the p.ppid table until
  2863                              <1> 	;	all processes are checked or a zombie is found.
  2864                              <1> 	;    2) If no zombies are found, a check is made to see if
  2865                              <1> 	;	there are any children at all. If there are none,
  2866                              <1> 	;	an error return is made. If there are, the parent's
  2867                              <1> 	;	status is set to 2 (waiting for child to die),
  2868                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2869                              <1> 	;	is made to wait on the next process.
  2870                              <1> 	;
  2871                              <1> 	; Calling sequence:
  2872                              <1> 	;	?
  2873                              <1> 	; Arguments:
  2874                              <1> 	;	-
  2875                              <1> 	; Inputs: - 
  2876                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2877                              <1> 	; ...............................................................
  2878                              <1> 	;				
  2879                              <1> 	
  2880                              <1> ; / wait for a process to die
  2881                              <1> 
  2882                              <1> syswait_0:
  2883 00003C91 0FB61D[9B6F0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2884                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2885 00003C98 D0E3                <1> 	shl	bl, 1
  2886                              <1> 	;shl	bx, 1
  2887                              <1> 		; asl r1 / x2 to get index into p.pid table
  2888 00003C9A 668B83[666C0000]    <1> 	mov	ax, [ebx+p.pid-2]
  2889                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2890 00003CA1 31F6                <1> 	xor	esi, esi
  2891                              <1> 		; clr r2
  2892 00003CA3 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2893                              <1> 	;xor 	cl, cl
  2894                              <1> 		; clr r3 / initialize reg 3
  2895                              <1> syswait_1: ; 1:
  2896                              <1> 	; 09/02/2022
  2897 00003CA5 46                  <1> 	inc	esi
  2898 00003CA6 46                  <1> 	inc	esi
  2899                              <1> 	;add	si, 2
  2900                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2901                              <1> 			  ; / search table of parent processes 
  2902                              <1> 			  ; / for this process name
  2903 00003CA7 663B86[866C0000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2904                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2905                              <1> 			            ; / process number
  2906 00003CAE 7531                <1> 	jne	short syswait_3
  2907                              <1> 		;bne 3f / branch if no match of parent process name
  2908                              <1> 	;inc	cx
  2909 00003CB0 FEC1                <1> 	inc	cl
  2910                              <1> 		;inc r3 / yes, a match, r3 indicates number of children
  2911                              <1> 	; 09/02/2022
  2912 00003CB2 D1EE                <1> 	shr	esi, 1
  2913                              <1> 	;shr	si, 1
  2914                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2915                              <1> 	; The possible states ('p.stat' values) of a process are:
  2916                              <1> 	;	0 = free or unused
  2917                              <1> 	;	1 = active
  2918                              <1> 	;	2 = waiting for a child process to die
  2919                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2920 00003CB4 80BE[C76C0000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2921                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2922 00003CBB 7522                <1> 	jne	short syswait_2
  2923                              <1> 		; bne 2f / no, skip it
  2924 00003CBD 88BE[C76C0000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2925                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2926                              <1> 	; 09/02/2022
  2927 00003CC3 D1E6                <1> 	shl	esi, 1
  2928                              <1> 	;shl	si, 1
  2929                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2930 00003CC5 0FB786[666C0000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2931 00003CCC A3[4C6F0000]        <1> 	mov	[u.r0], eax
  2932                              <1> 		; mov p.pid-2(r2),*u.r0 
  2933                              <1> 			      ; / put childs process name in (u.r0)
  2934                              <1> 	;
  2935                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2936                              <1> 	;
  2937                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2938                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2939                              <1> 	; system call loop from the application/program if it calls
  2940                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2941                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2942                              <1> 	;
  2943                              <1> 	; Note: syswait will return with error if there is not a
  2944                              <1> 	;       zombie or running process to wait.	
  2945                              <1> 	;
  2946                              <1> 	;sub	ax, ax
  2947                              <1> 	; 08/01/2022
  2948 00003CD1 29C0                <1> 	sub	eax, eax
  2949 00003CD3 668986[866C0000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2950 00003CDA E90AFEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2951                              <1> 	;
  2952                              <1> 	;jmp	sysret
  2953                              <1> 		; br sysret1 / return cause child is dead
  2954                              <1> syswait_2: ; 2:
  2955                              <1> 	; 09/02/2022
  2956 00003CDF D1E6                <1> 	shl	esi, 1
  2957                              <1> 	;shl	si, 1
  2958                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2959                              <1> syswait_3: ; 3:
  2960 00003CE1 6683FE20            <1> 	cmp	si, nproc+nproc
  2961                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2962 00003CE5 72BE                <1> 	jb	short syswait_1
  2963                              <1> 		; blt 1b / no, continue search
  2964                              <1> 	;and	cx, cx
  2965 00003CE7 20C9                <1> 	and	cl, cl
  2966                              <1> 		; tst r3 / one gets here if there are no children 
  2967                              <1> 		       ; / or children that are still active
  2968                              <1> 	; 30/10/2013
  2969 00003CE9 7515                <1> 	jnz	short syswait_4
  2970                              <1> 	;jz	error
  2971                              <1> 		; beq error1 / there are no children, error
  2972 00003CEB 890D[4C6F0000]      <1> 	mov	[u.r0], ecx ; 0
  2973                              <1> 	; 09/02/2022
  2974 00003CF1 C705[A16F0000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2974 00003CF9 0000                <1>
  2975                              <1> 			; miscellaneous/other errors
  2976 00003CFB E9C7FDFFFF          <1> 	jmp	error
  2977                              <1> syswait_4:
  2978 00003D00 8A1D[9B6F0000]      <1> 	mov	bl, [u.uno]
  2979                              <1> 		; movb u.uno,r1 / there are children so put 
  2980                              <1> 			      ; / parent process number in r1
  2981 00003D06 FE83[C76C0000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2982                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2983                              <1> 				  ; / other children to die
  2984                              <1> 	; 04/11/2013
  2985 00003D0C E873110000          <1> 	call	swap
  2986                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2987 00003D11 E97BFFFFFF          <1> 	jmp	syswait_0
  2988                              <1> 		; br syswait / wait on next process
  2989                              <1> 
  2990                              <1> sysfork: ; < create a new process >
  2991                              <1> 	; 26/02/2022
  2992                              <1> 	; 25/02/2022
  2993                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2994                              <1> 	; 18/09/2015
  2995                              <1> 	; 04/09/2015
  2996                              <1> 	; 02/09/2015
  2997                              <1> 	; 01/09/2015
  2998                              <1> 	; 28/08/2015
  2999                              <1> 	; 14/05/2015
  3000                              <1> 	; 10/05/2015
  3001                              <1> 	; 09/05/2015
  3002                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  3003                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  3004                              <1> 	;
  3005                              <1> 	; 'sysfork' creates a new process. This process is referred
  3006                              <1> 	; to as the child process. This new process core image is
  3007                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  3008                              <1> 	; distinction is the return location and the fact that (u.r0)
  3009                              <1> 	; in the old process (parent) contains the process id (p.pid)
  3010                              <1> 	; of the new process (child). This id is used by 'syswait'.
  3011                              <1> 	; 'sysfork' works in the following manner: 	
  3012                              <1> 	;    1) The process status table (p.stat) is searched to find
  3013                              <1> 	;	a process number that is unused. If none are found
  3014                              <1> 	;	an error occurs.
  3015                              <1> 	;    2) when one is found, it becomes the child process number
  3016                              <1> 	;	and it's status (p.stat) is set to active.
  3017                              <1> 	;    3) If the parent had a control tty, the interrupt 
  3018                              <1> 	;	character in that tty buffer is cleared.
  3019                              <1> 	;    4) The child process is put on the lowest priority run 
  3020                              <1> 	;	queue via 'putlu'.
  3021                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  3022                              <1> 	;	it is a unique number) and is put in the child's unique
  3023                              <1> 	;	identifier; process id (p.pid).
  3024                              <1> 	;    6) The process name of the parent is then obtained and
  3025                              <1> 	;	placed in the unique identifier of the parent process
  3026                              <1> 	;	name is then put in 'u.r0'.	
  3027                              <1> 	;    7) The child process is then written out on disk by
  3028                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  3029                              <1> 	;	and the child is born. (The child process is written 
  3030                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  3031                              <1> 	;	number.)
  3032                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  3033                              <1> 	;    9) The child process name is put in 'u.r0'.
  3034                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  3035                              <1> 	;	create the return address for the parent process.
  3036                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  3037                              <1> 	;	the parent has opened. For each file the parent has
  3038                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  3039                              <1> 	;	to indicate that the child process also has opened
  3040                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  3041                              <1> 	;
  3042                              <1> 	; Calling sequence:
  3043                              <1> 	;	from shell ?
  3044                              <1> 	; Arguments:
  3045                              <1> 	;	-
  3046                              <1> 	; Inputs: -
  3047                              <1> 	; Outputs: *u.r0 - child process name
  3048                              <1> 	; ...............................................................
  3049                              <1> 	;	
  3050                              <1> 	; Retro UNIX 8086 v1 modification: 
  3051                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  3052                              <1> 	;	= process id of child a parent process returns
  3053                              <1> 	;	= process id of parent when a child process returns
  3054                              <1> 	;
  3055                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3056                              <1> 	;	in following manner: (with an example: c library, fork)
  3057                              <1> 	;	
  3058                              <1> 	;	1:
  3059                              <1> 	;		sys	fork
  3060                              <1> 	;			br 1f  / child process returns here
  3061                              <1> 	;		bes	2f     / parent process returns here
  3062                              <1> 	;		/ pid of new process in r0
  3063                              <1> 	;		rts	pc
  3064                              <1> 	;	2: / parent process condionally branches here
  3065                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3066                              <1> 	;		rts	pc
  3067                              <1> 	;
  3068                              <1> 	;	1: / child process brances here
  3069                              <1> 	;		clr	r0   / pid = 0 in child process
  3070                              <1> 	;		rts	pc
  3071                              <1> 	;
  3072                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3073                              <1> 	;		// pid = fork();
  3074                              <1> 	;		//
  3075                              <1> 	;		// pid == 0 in child process; 
  3076                              <1> 	;		// pid == -1 means error return
  3077                              <1> 	;		// in child, 
  3078                              <1> 	;		//	parents id is in par_uid if needed
  3079                              <1> 	;		
  3080                              <1> 	;		_fork:
  3081                              <1> 	;			mov	$.fork,eax
  3082                              <1> 	;			int	$0x30
  3083                              <1> 	;			jmp	1f
  3084                              <1> 	;			jnc	2f
  3085                              <1> 	;			jmp	cerror
  3086                              <1> 	;		1:
  3087                              <1> 	;			mov	eax,_par_uid
  3088                              <1> 	;			xor	eax,eax
  3089                              <1> 	;		2:
  3090                              <1> 	;			ret
  3091                              <1> 	;
  3092                              <1> 	;	In Retro UNIX 8086 v1,
  3093                              <1> 	;	'sysfork' returns in following manner:
  3094                              <1> 	;	
  3095                              <1> 	;		mov	ax, sys_fork
  3096                              <1> 	;		mov	bx, offset @f ; routine for child
  3097                              <1> 	;		int	20h
  3098                              <1> 	;		jc	error
  3099                              <1> 	;		
  3100                              <1> 	;	; Routine for parent process here (just after 'jc')
  3101                              <1> 	;		mov	word ptr [pid_of_child], ax
  3102                              <1> 	;		jmp	next_routine_for_parent	
  3103                              <1> 	;
  3104                              <1> 	;	@@: ; routine for child process here				
  3105                              <1> 	;		....	
  3106                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3107                              <1> 	;	       for child process by using BX input.
  3108                              <1> 	;	      (at first, parent process will return then 
  3109                              <1> 	;	      child process will return -after swapped in-
  3110                              <1> 	;	      'syswait' is needed in parent process
  3111                              <1> 	;	      if return from child process will be waited for.)
  3112                              <1> 	;	  				
  3113                              <1> 	
  3114                              <1> ; / create a new process
  3115                              <1> 	; EBX = return address for child process 
  3116                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3117 00003D16 31F6                <1> 	xor 	esi, esi
  3118                              <1> 		; clr r1
  3119                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3120 00003D18 46                  <1> 	inc	esi
  3121                              <1> 		; inc r1
  3122 00003D19 80BE[C76C0000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3123                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3124 00003D20 760B                <1> 	jna	short sysfork_2	
  3125                              <1> 		; beq 1f / it's unused so branch
  3126 00003D22 6683FE10            <1> 	cmp	si, nproc
  3127                              <1> 		; cmp r1,$nproc / all processes checked
  3128 00003D26 72F0                <1> 	jb	short sysfork_1
  3129                              <1> 		; blt 1b / no, branch back
  3130                              <1> 	;
  3131                              <1> 	; Retro UNIX 8086 v1. modification:
  3132                              <1> 	;	Parent process returns from 'sysfork' to address 
  3133                              <1> 	;	which is just after 'sysfork' system call in parent
  3134                              <1> 	;	process. Child process returns to address which is put
  3135                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3136                              <1> 	;
  3137                              <1> 		;add $2,18.(sp) / add 2 to pc when trap occured, points
  3138                              <1> 		             ; / to old process return
  3139                              <1> 		; br error1 / no room for a new process
  3140                              <1> sysfork_0:
  3141 00003D28 E99AFDFFFF          <1> 	jmp	error
  3142                              <1> sysfork_2: ; 1:
  3143 00003D2D E884F0FFFF          <1> 	call	allocate_page
  3144                              <1> 	;jc	error
  3145                              <1> 	; 08/01/2022
  3146 00003D32 72F4                <1> 	jc	short sysfork_0
  3147                              <1> 
  3148 00003D34 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3149                              <1> 	; Retro UNIX 386 v1 modification!
  3150 00003D35 E875F2FFFF          <1> 	call	duplicate_page_dir
  3151                              <1> 		; EAX = New page directory 
  3152 00003D3A 7308                <1> 	jnc	short sysfork_3
  3153 00003D3C 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3154 00003D3D E83CF2FFFF          <1> 	call 	deallocate_page
  3155                              <1> 	;jmp	error
  3156                              <1> 	; 08/01/2022
  3157 00003D42 EBE4                <1> 	jmp	short sysfork_0 ; error
  3158                              <1> sysfork_3:
  3159                              <1> 	; Retro UNIX 386 v1 modification !
  3160 00003D44 56                  <1> 	push	esi
  3161 00003D45 E8B1110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3162                              <1> 		      ; and interrupt return components (for IRET)
  3163 00003D4A 8705[A56F0000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3164 00003D50 A3[A96F0000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3165 00003D55 5E                  <1> 	pop	esi
  3166 00003D56 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3167                              <1> 		; [u.usp] = esp
  3168 00003D57 89F7                <1> 	mov	edi, esi
  3169                              <1> 	;shl	di, 2
  3170                              <1> 	; 08/01/2022
  3171 00003D59 C1E702              <1> 	shl	edi, 2
  3172 00003D5C 8987[D46C0000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3173 00003D62 A3[9C6F0000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3174                              <1> 	; 28/08/2015
  3175 00003D67 0FB605[9B6F0000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3176                              <1> 		; movb u.uno,-(sp) / save parent process number
  3177 00003D6E 89C7                <1> 	mov	edi, eax
  3178 00003D70 50                  <1>         push	eax ; ** 
  3179 00003D71 8A87[A76C0000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3180                              <1> 		; 18/09/2015
  3181 00003D77 8886[A76C0000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3182                              <1> 	; 26/02/2022 (p.waitc is not used)
  3183                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3184                              <1> 	; 25/02/2022 (BugFix)
  3185                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3186                              <1> 	;			   ; ah - reset child's wait channel	
  3187 00003D7D 89F0                <1> 	mov	eax, esi
  3188 00003D7F A2[9B6F0000]        <1> 	mov	[u.uno], al ; child process number
  3189                              <1> 		;movb r1,u.uno / set child process number to r1
  3190 00003D84 FE86[C76C0000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3191                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3192                              <1> 				; / process to active status
  3193                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3194                              <1> 			      ; / control tty buffer in r2
  3195                              <1>                 ; beq 2f / branch, if no such tty assigned
  3196                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3197                              <1> 	; 2:
  3198 00003D8A 53                  <1> 	push	ebx  ; * return address for the child process
  3199                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3200                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3201                              <1> 		; mov $runq+4,r2
  3202 00003D8B E8C1110000          <1> 	call	putlu 
  3203                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3204                              <1> 			   ; / run queue
  3205                              <1> 	; 08/01/2022
  3206 00003D90 D1E6                <1> 	shl	esi, 1
  3207                              <1> 	;shl	si, 1
  3208                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3209                              <1> 		       ; / into p.pid table
  3210 00003D92 66FF05[386F0000]    <1> 	inc	word [mpid]
  3211                              <1> 		; inc mpid / increment m.pid; get a new process name
  3212 00003D99 66A1[386F0000]      <1> 	mov	ax, [mpid]
  3213 00003D9F 668986[666C0000]    <1> 	mov	[esi+p.pid-2], ax
  3214                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3215                              <1> 				    ; / in child process' name slot
  3216 00003DA6 5A                  <1> 	pop	edx  ; * return address for the child process
  3217                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3218 00003DA7 5B                  <1>   	pop	ebx  ; **
  3219                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3220                              <1> 		; movb (sp),r2 / put parent process number in r2
  3221                              <1> 	; 08/01/2022
  3222 00003DA8 D1E3                <1> 	shl	ebx, 1
  3223                              <1> 	;shl 	bx, 1
  3224                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3225                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3226 00003DAA 668B83[666C0000]    <1> 	mov	ax, [ebx+p.pid-2]
  3227                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3228                              <1> 				   ; / process
  3229 00003DB1 668986[866C0000]    <1> 	mov	[esi+p.ppid-2], ax
  3230                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3231                              <1> 			  ; / in parent process slot for child
  3232 00003DB8 A3[4C6F0000]        <1> 	mov	[u.r0], eax	
  3233                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3234                              <1> 			     ; / at location where r0 was saved
  3235 00003DBD 8B2D[446F0000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3236 00003DC3 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3237                              <1> 			   ; * return address for the child process
  3238                              <1> 		; mov $sysret1,-(sp) /
  3239                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3240                              <1> 			      ; / user is swapped out
  3241                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3242                              <1> 	; 04/09/2015 - 01/09/2015
  3243                              <1> 	; [u.usp] = esp
  3244 00003DC6 68[E73A0000]        <1> 	push	sysret ; ***
  3245 00003DCB 8925[486F0000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3246                              <1> 			     ; (for child process)	
  3247 00003DD1 31C0                <1> 	xor 	eax, eax
  3248 00003DD3 66A3[7C6F0000]      <1> 	mov 	[u.ttyp], ax ; 0
  3249                              <1> 	;
  3250 00003DD9 E81D110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3251                              <1> 		;jsr r0,wswap / put child process out on drum
  3252                              <1> 		;jsr r0,unpack / unpack user stack
  3253                              <1> 		;mov u.usp,sp / restore user stack pointer
  3254                              <1> 		; tst (sp)+ / bump stack pointer
  3255                              <1> 	; Retro UNIX 386 v1 modification !
  3256 00003DDE 58                  <1> 	pop	eax ; ***
  3257                              <1> 	; 08/01/2022
  3258 00003DDF D1E3                <1> 	shl	ebx, 1
  3259                              <1> 	;shl 	bx, 1
  3260 00003DE1 8B83[D46C0000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3261 00003DE7 E838110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3262                              <1> 		      ; registers and return address (for IRET)
  3263                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3264 00003DEC 0FB705[386F0000]    <1>         movzx   eax, word [mpid]
  3265 00003DF3 A3[4C6F0000]        <1> 	mov	[u.r0], eax
  3266                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3267                              <1> 			       ; / where r0 was saved
  3268                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3269                              <1> 			          ; / process return
  3270                              <1> 	;xor	ebx, ebx
  3271 00003DF8 31F6                <1> 	xor     esi, esi
  3272                              <1> 		;clr r1
  3273                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3274                              <1> 	      ; / opened by the parent process
  3275                              <1> 	; 01/09/2015
  3276                              <1> 	;xor	bh, bh
  3277                              <1> 	;mov 	bl, [esi+u.fp]
  3278 00003DFA 8A86[526F0000]      <1> 	mov 	al, [esi+u.fp]
  3279                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3280                              <1>         ;or	bl, bl
  3281 00003E00 08C0                <1> 	or	al, al
  3282 00003E02 740C                <1> 	jz	short sysfork_5	
  3283                              <1> 		; beq 2f / file has not been opened by parent, 
  3284                              <1> 		       ; / so branch
  3285 00003E04 B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3286 00003E06 F6E4                <1> 	mul	ah
  3287                              <1> 	;;movzx	ebx, ax
  3288                              <1> 	;mov	bx, ax
  3289 00003E08 89C3                <1> 	mov	ebx, eax ; 08/01/2022
  3290                              <1> 	;shl	bx, 3
  3291                              <1> 		; asl r2 / multiply by 8
  3292                              <1>        		; asl r2 / to get index into fsp table
  3293                              <1>        		; asl r2
  3294 00003E0A FE83[166D0000]      <1>   	inc     byte [ebx+fsp-2]
  3295                              <1> 		; incb fsp-2(r2) / increment number of processes
  3296                              <1> 			     ; / using file, because child will now be
  3297                              <1> 			     ; / using this file
  3298                              <1> sysfork_5: ; 2:
  3299 00003E10 46                  <1>         inc     esi
  3300                              <1> 		; inc r1 / get next open file
  3301 00003E11 6683FE0A            <1>         cmp     si, 10
  3302                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3303                              <1> 			  ; / can be opened
  3304 00003E15 72E3                <1> 	jb	short sysfork_4	
  3305                              <1> 		; blt 1b / check next entry
  3306 00003E17 E9CBFCFFFF          <1> 	jmp	sysret
  3307                              <1> 		; br sysret1
  3308                              <1> 
  3309                              <1> sysread: ; < read from file >
  3310                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3311                              <1> 	; 13/05/2015
  3312                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3313                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3314                              <1> 	;
  3315                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3316                              <1> 	; characters to be read. If finds the file from the file
  3317                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3318                              <1> 	; is returned from a successful open call (sysopen).
  3319                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3320                              <1> 	; is read into core via 'readi'.
  3321                              <1> 	;
  3322                              <1> 	; Calling sequence:
  3323                              <1> 	;	sysread; buffer; nchars
  3324                              <1> 	; Arguments:
  3325                              <1> 	;	buffer - location of contiguous bytes where 
  3326                              <1> 	;		 input will be placed.
  3327                              <1> 	;	nchars - number of bytes or characters to be read.
  3328                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3329                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3330                              <1> 	; ...............................................................
  3331                              <1> 	;				
  3332                              <1> 	; Retro UNIX 8086 v1 modification: 
  3333                              <1> 	;       'sysread' system call has three arguments; so,
  3334                              <1> 	;	* 1st argument, file descriptor is in BX register
  3335                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3336                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3337                              <1> 	;
  3338                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3339                              <1> 	;	to the user with number of bytes read. 
  3340                              <1> 	;
  3341 00003E1C E840000000          <1> 	call	rw1
  3342                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3343                              <1> 	;	; jsr r0,rw1 / get i-number of file to be read into r1
  3344                              <1>        	; 24/12/2021
  3345 00003E21 7239                <1> 	jc	short sysread_err
  3346 00003E23 F6C480              <1> 	test	ah, 80h
  3347                              <1> 		; tst r1 / negative i-number?
  3348 00003E26 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3349                              <1> 	;jnz	error
  3350                              <1> 		; ble error1 / yes, error 1 to read
  3351                              <1> 			   ; / it should be positive
  3352 00003E28 E88B150000          <1> 	call	readi
  3353                              <1> 		; jsr r0,readi / read data into core
  3354 00003E2D EB14                <1> 	jmp	short rw0
  3355                              <1> 		; br 1f
  3356                              <1> 
  3357                              <1> syswrite: ; < write to file >
  3358                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3359                              <1> 	; 13/05/2015
  3360                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3361                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3362                              <1> 	;
  3363                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3364                              <1> 	; and the number of characters to write. If finds the file
  3365                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3366                              <1> 	; descriptor is returned from a successful open or create call
  3367                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3368                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3369                              <1> 	;
  3370                              <1> 	; Calling sequence:
  3371                              <1> 	;	syswrite; buffer; nchars
  3372                              <1> 	; Arguments:
  3373                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3374                              <1> 	;	nchars - number of characters to be written.
  3375                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3376                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3377                              <1> 	; ...............................................................
  3378                              <1> 	;				
  3379                              <1> 	; Retro UNIX 8086 v1 modification: 
  3380                              <1> 	;       'syswrite' system call has three arguments; so,
  3381                              <1> 	;	* 1st argument, file descriptor is in BX register
  3382                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3383                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3384                              <1> 	;
  3385                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3386                              <1> 	;	to the user with number of bytes written. 
  3387                              <1> 	;
  3388 00003E2F E82D000000          <1> 	call	rw1
  3389                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3390                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3391                              <1>        	; 24/12/2021
  3392 00003E34 7226                <1> 	jc	short syswrite_err
  3393 00003E36 F6C480              <1>         test	ah, 80h
  3394                              <1> 		; tst r1 / positive i-number ?
  3395 00003E39 7417                <1>         jz	short rw3 ; 13/05/2015
  3396                              <1> 	;jz	error
  3397                              <1> 		; bge error1 / yes, error 1 
  3398                              <1> 			   ; / negative i-number means write
  3399 00003E3B 66F7D8              <1>         neg	ax
  3400                              <1> 		; neg r1 / make it positive
  3401 00003E3E E863170000          <1> 	call	writei
  3402                              <1>         	; jsr r0,writei / write data
  3403                              <1> rw0: ; 1:
  3404 00003E43 A1[746F0000]        <1>         mov	eax, [u.nread]
  3405 00003E48 A3[4C6F0000]        <1> 	mov	[u.r0], eax
  3406                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3407                              <1> 				  ; / into (u.r0)
  3408 00003E4D E995FCFFFF          <1> 	jmp	sysret
  3409                              <1>         	; br sysret1
  3410                              <1> 
  3411                              <1> rw3: 
  3412                              <1> 	; 13/05/2015
  3413 00003E52 C705[A16F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3413 00003E5A 0000                <1>
  3414                              <1> 	;stc
  3415                              <1> 	;retn
  3416                              <1> 	; 24/12/2021 (BugFix)
  3417                              <1> sysread_err:
  3418                              <1> syswrite_err:
  3419 00003E5C E966FCFFFF          <1> 	jmp	error
  3420                              <1> 
  3421                              <1> rw1:	
  3422                              <1> 	; 14/05/2015
  3423                              <1> 	; 13/05/2015
  3424                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3425                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3426                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3427                              <1> 	;
  3428                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3429                              <1> 				;(in the user's virtual memory space)
  3430                              <1> 	;mov	[u.count], edx 
  3431                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3432                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3433                              <1> 	;;mov	eax, ebx ; file descriptor
  3434                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3435                              <1> 		             ; / (index to u.fp table) in r1
  3436                              <1> 	; 13/05/2015
  3437 00003E61 C705[4C6F0000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3437 00003E69 0000                <1>
  3438                              <1> 	;
  3439                              <1> 	;; call	getf
  3440                              <1>         ; eBX = File descriptor
  3441 00003E6B E8330B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3442                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3443                              <1> 	; AX = I-number of the file ; negative i-number means write
  3444                              <1> 	; 13/05/2015
  3445 00003E70 6683F801            <1> 	cmp 	ax, 1
  3446 00003E74 7217                <1> 	jb	short rw2
  3447                              <1> 	;
  3448 00003E76 890D[6C6F0000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3449                              <1> 				;(in the user's virtual memory space)
  3450 00003E7C 8915[706F0000]      <1> 	mov	[u.count], edx 
  3451                              <1> 	; 14/05/2015
  3452 00003E82 C705[A16F0000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3452 00003E8A 0000                <1>
  3453 00003E8C C3                  <1> 	retn
  3454                              <1>         	; rts r0
  3455                              <1> rw2:
  3456                              <1> 	; 13/05/2015
  3457 00003E8D C705[A16F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3457 00003E95 0000                <1>
  3458 00003E97 C3                  <1> 	retn
  3459                              <1> 
  3460                              <1> sysopen: ;<open file>
  3461                              <1> 	; 09/01/2022
  3462                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3463                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3464                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3465                              <1> 	;
  3466                              <1> 	; 'sysopen' opens a file in following manner:
  3467                              <1> 	;    1) The second argument in a sysopen says whether to
  3468                              <1> 	;	open the file ro read (0) or write (>0).
  3469                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3470                              <1> 	;    3) The file is opened by 'iopen'.
  3471                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3472                              <1> 	;	and the user's open file list - u.fp.
  3473                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3474                              <1> 	;	b) An entry for the file is created in the fsp table.
  3475                              <1> 	;	c) The number of this entry is put on u.fp list.
  3476                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3477                              <1> 	;	   to by u.r0.
  3478                              <1> 	;
  3479                              <1> 	; Calling sequence:
  3480                              <1> 	;	sysopen; name; mode
  3481                              <1> 	; Arguments:
  3482                              <1> 	;	name - file name or path name
  3483                              <1> 	;	mode - 0 to open for reading
  3484                              <1> 	;	       1 to open for writing
  3485                              <1> 	; Inputs: (arguments)
  3486                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3487                              <1> 	;		  is put into r0's location on the stack.	
  3488                              <1> 	; ...............................................................
  3489                              <1> 	;				
  3490                              <1> 	; Retro UNIX 8086 v1 modification: 
  3491                              <1> 	;       'sysopen' system call has two arguments; so,
  3492                              <1> 	;	* 1st argument, name is pointed to by BX register
  3493                              <1> 	;	* 2nd argument, mode is in CX register
  3494                              <1> 	;
  3495                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3496                              <1> 	;	to the user with the file descriptor/number 
  3497                              <1> 	;	(index to u.fp list).
  3498                              <1> 	;
  3499                              <1> 	;call	arg2
  3500                              <1> 	; * name - 'u.namep' points to address of file/path name
  3501                              <1> 	;          in the user's program segment ('u.segmnt')
  3502                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3503                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3504                              <1> 	;          which is on top of stack.
  3505                              <1> 	;
  3506                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3507                              <1> 	;
  3508                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3509                              <1> 
  3510 00003E98 891D[646F0000]      <1> 	mov	[u.namep], ebx
  3511                              <1> 	; 24/12/2021 (cx -> ecx)
  3512 00003E9E 51                  <1> 	push	ecx ; * 
  3513 00003E9F E8300B0000          <1> 	call	namei
  3514                              <1> 		; jsr r0,namei / i-number of file in r1
  3515                              <1>      	;and	ax, ax
  3516                              <1> 	;jz	error ; File not found
  3517 00003EA4 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3518                              <1> 	;jc	error ; 27/05/2013
  3519                              <1> 		; br  error2 / file not found
  3520                              <1>    	; 24/12/2021
  3521                              <1> 	;pop	edx ; * ; mode
  3522                              <1> 	;push	edx ; *
  3523 00003EA6 8B1424              <1> 	mov	edx, [esp] ; *
  3524                              <1> 	; edx = open mode (0 or 1)
  3525                              <1> 	;or	dx, dx
  3526 00003EA9 08D2                <1> 	or	dl, dl
  3527                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3528                              <1> 		         ; / 0 means, open for read)
  3529 00003EAB 7403                <1> 	jz	short sysopen_0
  3530                              <1> 		; beq 1f / yes, leave i-number positive
  3531                              <1> syscreat_0: ; 27/12/2015
  3532 00003EAD 66F7D8              <1> 	neg	ax
  3533                              <1>         	; neg r1 / open for writing so make i-number negative
  3534                              <1> sysopen_0: ;1:
  3535 00003EB0 E8141B0000          <1> 	call	iopen
  3536                              <1> 		;jsr r0,iopen / open file whose i-number is in r1
  3537 00003EB5 5A                  <1> 	pop	edx ; * ; mode ; 24/12/2021
  3538                              <1> 	;and	dx, dx
  3539 00003EB6 20D2                <1> 	and	dl, dl
  3540                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3541 00003EB8 7403                <1> 	jz	short sysopen_2
  3542                              <1>         	; beq op1 / is open for read op1
  3543                              <1> sysopen_1: ;op0:
  3544 00003EBA 66F7D8              <1> 	neg	ax
  3545                              <1>         	; neg r1 
  3546                              <1> 	;; NOTE: iopen always make i-number positive.
  3547                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3548                              <1> sysopen_2: ;op1:
  3549 00003EBD 31F6                <1>         xor     esi, esi
  3550                              <1>         	; clr r2 / clear registers
  3551 00003EBF 31DB                <1>         xor     ebx, ebx
  3552                              <1> 		; clr r3
  3553                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3554 00003EC1 389E[526F0000]      <1>         cmp     [esi+u.fp], bl ; 0
  3555                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3556 00003EC7 7625                <1>         jna      short sysopen_4
  3557                              <1> 		; beq 1f / if byte in list is 0 branch
  3558 00003EC9 46                  <1>         inc     esi
  3559                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3560 00003ECA 6683FE0A            <1>         cmp     si, 10  ; OPENFILES
  3561                              <1> 		; cmp r2,$10. / reached end of list?
  3562 00003ECE 72F1                <1> 	jb	short sysopen_3
  3563                              <1> 		; blt 1b / no, go back
  3564                              <1> toomanyf:
  3565                              <1> 	; 14/05/2015
  3566 00003ED0 C705[A16F0000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3566 00003ED8 0000                <1>
  3567 00003EDA E9E8FBFFFF          <1> 	jmp	error
  3568                              <1>         	; br error2 / yes, error (no files open)
  3569                              <1> fnotfound: 
  3570                              <1> 	; 14/05/2015
  3571 00003EDF C705[A16F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3571 00003EE7 0000                <1>
  3572 00003EE9 E9D9FBFFFF          <1> 	jmp	error
  3573                              <1> 
  3574                              <1> sysopen_4: ; 1:
  3575 00003EEE 6683BB[186D0000]00  <1>         cmp     word [ebx+fsp], 0
  3576                              <1> 		; tst fsp(r3) / scan fsp entries
  3577 00003EF6 760D                <1>         jna     short sysopen_5
  3578                              <1> 		; beq 1f / if 0 branch
  3579                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3580 00003EF8 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3581                              <1> 		; add $8.,r3 / add 8 to r3 
  3582                              <1> 			; / to bump it to next entry mfsp table
  3583 00003EFC 6681FBF401          <1>         cmp     bx, nfiles*10
  3584                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3585 00003F01 72EB                <1> 	jb	short sysopen_4
  3586                              <1>        		; blt 1b / no, back
  3587                              <1> 	;jmp	error
  3588                              <1>         ;	; br error2 / yes, error
  3589                              <1> 	; 24/12/2021
  3590 00003F03 EBCB                <1> 	jmp	short toomanyf
  3591                              <1> 
  3592                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3593 00003F05 668983[186D0000]    <1>         mov     [ebx+fsp], ax
  3594                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3595                              <1> 			; / into next available entry in fsp table,
  3596                              <1> 	; 09/01/2022
  3597                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3598                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3599                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3600                              <1> 	;xor	edi, edi
  3601                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3602                              <1> 	;	; clr fsp+4(r3)
  3603                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3604                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3605 00003F0C 31C0                <1> 	xor	eax, eax
  3606 00003F0E 8983[1C6D0000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3607 00003F14 668983[206D0000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3608                              <1> 
  3609 00003F1B A0[2F6F0000]        <1> 	mov	al, [cdev]
  3610 00003F20 668983[1A6D0000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3611                              <1> 
  3612 00003F27 89D8                <1>   	mov	eax, ebx
  3613 00003F29 B30A                <1> 	mov	bl, 10
  3614 00003F2B F6F3                <1> 	div	bl 
  3615                              <1> 		; asr r3
  3616                              <1> 		; asr r3 / divide by 8 
  3617                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3618 00003F2D FEC0                <1> 	inc	al
  3619                              <1>         	; inc r3 / add 1 to get fsp entry number
  3620 00003F2F 8886[526F0000]      <1>         mov     [esi+u.fp], al
  3621                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3622                              <1> 			; / next available slot in u.fp list
  3623 00003F35 8935[4C6F0000]      <1>         mov     [u.r0], esi
  3624                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3625                              <1> 			     ; / into r0 loc on stack
  3626 00003F3B E9A7FBFFFF          <1>         jmp	sysret
  3627                              <1> 		; br sysret2
  3628                              <1> 
  3629                              <1> 	;
  3630                              <1> 	; 'fsp' table (10 bytes/entry)
  3631                              <1> 	; bit 15				   bit 0
  3632                              <1> 	; ---|-------------------------------------------
  3633                              <1> 	; r/w|		i-number of open file
  3634                              <1> 	; ---|-------------------------------------------
  3635                              <1> 	;		   device number
  3636                              <1> 	; -----------------------------------------------
  3637                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3638                              <1> 	; -----------------------------------------------
  3639                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3640                              <1> 	; ----------------------|------------------------
  3641                              <1> 	;  flag that says file 	| number of processes
  3642                              <1> 	;   has been deleted	| that have file open 
  3643                              <1> 	; ----------------------|------------------------
  3644                              <1> 	;
  3645                              <1> 
  3646                              <1> syscreat: ; < create file >
  3647                              <1> 	; 24/12/2021
  3648                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3649                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3650                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3651                              <1> 	;
  3652                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3653                              <1> 	; u.namep points to name of the file and mode is put
  3654                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3655                              <1> 	; If the file aready exists, it's mode and owner remain 
  3656                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3657                              <1> 	; did not exist, an i-node is created with the new mode via
  3658                              <1> 	; 'maknod' whether or not the file already existed, it is
  3659                              <1> 	; open for writing. The fsp table is then searched for a free
  3660                              <1> 	; entry. When a free entry is found, proper data is placed
  3661                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3662                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3663                              <1> 	; is put in the user's r0. 			
  3664                              <1> 	;
  3665                              <1> 	; Calling sequence:
  3666                              <1> 	;	syscreate; name; mode
  3667                              <1> 	; Arguments:
  3668                              <1> 	;	name - name of the file to be created
  3669                              <1> 	;	mode - mode of the file to be created
  3670                              <1> 	; Inputs: (arguments)
  3671                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3672                              <1> 	;		   (the file descriptor of new file)
  3673                              <1> 	; ...............................................................
  3674                              <1> 	;				
  3675                              <1> 	; Retro UNIX 8086 v1 modification: 
  3676                              <1> 	;       'syscreate' system call has two arguments; so,
  3677                              <1> 	;	* 1st argument, name is pointed to by BX register
  3678                              <1> 	;	* 2nd argument, mode is in CX register
  3679                              <1> 	;
  3680                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3681                              <1> 	;	to the user with the file descriptor/number 
  3682                              <1> 	;	(index to u.fp list).
  3683                              <1> 	;
  3684                              <1> 	;call	arg2
  3685                              <1> 	; * name - 'u.namep' points to address of file/path name
  3686                              <1> 	;          in the user's program segment ('u.segmnt')
  3687                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3688                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3689                              <1> 	;          which is on top of stack.
  3690                              <1> 	;
  3691                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3692                              <1> 			    ; / on stack
  3693 00003F40 891D[646F0000]      <1> 	mov	[u.namep], ebx ; file name address
  3694                              <1> 	;push	cx ; mode
  3695                              <1> 	; 24/12/2021
  3696 00003F46 51                  <1> 	push	ecx ; cx = mode (permission flags)
  3697 00003F47 E8880A0000          <1> 	call 	namei        	
  3698                              <1> 		; jsr r0,namei / get the i-number
  3699                              <1>         ;and	ax, ax
  3700                              <1> 	;jz	short syscreat_2	       	
  3701 00003F4C 721B                <1> 	jc	short syscreat_2
  3702                              <1> 		; br  2f / if file doesn't exist 2f
  3703                              <1> 	; 27/12/2015
  3704 00003F4E 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3705                              <1>         ;jb	syscreat_0 ; yes
  3706                              <1> 	; 24/12/2021
  3707 00003F52 7305                <1> 	jnb	short syscreat_1
  3708 00003F54 E954FFFFFF          <1> 	jmp	syscreat_0
  3709                              <1> syscreat_1:
  3710 00003F59 66F7D8              <1> 	neg 	ax
  3711                              <1>         	; neg r1 / if file already exists make i-number 
  3712                              <1> 		       ; / negative (open for writing)
  3713 00003F5C E8681A0000          <1> 	call	iopen
  3714                              <1>         	; jsr r0,iopen /
  3715 00003F61 E8AA130000          <1> 	call	itrunc
  3716                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3717                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3718                              <1> 	; 04/12/2021
  3719 00003F66 59                  <1> 	pop	ecx
  3720                              <1> 	; 08/01/2022
  3721 00003F67 EB0E                <1> 	jmp	short syscreat_3
  3722                              <1>         ;jmp	sysopen_1
  3723                              <1>         	; br op0
  3724                              <1> syscreat_2: ; 2: / file doesn't exist
  3725                              <1> 	;pop	ax
  3726                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3727                              <1> 	; 24/12/2021
  3728 00003F69 58                  <1> 	pop	eax  ; ax = mode (permission flags)
  3729 00003F6A 30E4                <1> 	xor	ah, ah	
  3730                              <1>         	; bic $!377,r1 / clear upper byte
  3731 00003F6C E86F0D0000          <1> 	call 	maknod
  3732                              <1>         	; jsr r0,maknod / make an i-node for this file
  3733 00003F71 66A1[7E6F0000]      <1> 	mov	ax, [u.dirbuf]
  3734                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3735                              <1> 			        ; / for this new file in r1
  3736                              <1> syscreat_3:
  3737 00003F77 E93EFFFFFF          <1>         jmp     sysopen_1
  3738                              <1>         	; br op0 / open the file
  3739                              <1> 
  3740                              <1> sysmkdir: ; < make directory >
  3741                              <1> 	; 26/02/2022
  3742                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3743                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3744                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3745                              <1> 	;
  3746                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3747                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3748                              <1> 	; The special entries '.' and '..' are not present.
  3749                              <1> 	; Errors are indicated if the directory already exists or		
  3750                              <1> 	; user is not the super user. 
  3751                              <1> 	;
  3752                              <1> 	; Calling sequence:
  3753                              <1> 	;	sysmkdir; name; mode
  3754                              <1> 	; Arguments:
  3755                              <1> 	;	name - points to the name of the directory
  3756                              <1> 	;	mode - mode of the directory
  3757                              <1> 	; Inputs: (arguments)
  3758                              <1> 	; Outputs: -
  3759                              <1> 	;    (sets 'directory' flag to 1; 
  3760                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3761                              <1> 	; ...............................................................
  3762                              <1> 	;				
  3763                              <1> 	; Retro UNIX 8086 v1 modification: 
  3764                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3765                              <1> 	;	* 1st argument, name is pointed to by BX register
  3766                              <1> 	;	* 2nd argument, mode is in CX register
  3767                              <1> 	;
  3768                              <1> 		
  3769                              <1> ; / make a directory
  3770                              <1> 
  3771                              <1> 	;call	arg2
  3772                              <1> 	; * name - 'u.namep' points to address of file/path name
  3773                              <1> 	;          in the user's program segment ('u.segmnt')
  3774                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3775                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3776                              <1> 	;          which is on top of stack.
  3777                              <1> 
  3778                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3779                              <1> 			    ; / on stack
  3780 00003F7C 891D[646F0000]      <1> 	mov	[u.namep], ebx
  3781                              <1> 	;push	cx ; mode
  3782                              <1> 	; 24/12/2021
  3783 00003F82 51                  <1> 	push	ecx ; cx = mode
  3784 00003F83 E84C0A0000          <1> 	call	namei
  3785                              <1>         	; jsr r0,namei / get the i-number
  3786                              <1>         	;     br .+4 / if file not found branch around error
  3787                              <1>         ;xor 	ax, ax
  3788                              <1> 	;jnz	error
  3789 00003F88 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3790                              <1> 	;jnc	error	
  3791                              <1> 		; br  error2 / directory already exists (error)
  3792 00003F8A 803D[986F0000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3793                              <1>         	;tstb u.uid / is user the super user
  3794                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3795                              <1> 	;;jna	error
  3796                              <1> 	; 26/02/2022 (BugFix)
  3797 00003F91 7721                <1> 	ja	short dir_access_err
  3798                              <1>         	;bne error2 / no, not allowed
  3799                              <1> 	;pop	ax
  3800                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  3801                              <1> 	; 24/12/2021
  3802 00003F93 58                  <1> 	pop	eax  ; ax = mode
  3803 00003F94 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3804                              <1>         	;bic $!317,r1 / all but su and ex
  3805                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3806 00003F98 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3807                              <1>         	;bis $40000,r1 / directory flag
  3808 00003F9B E8400D0000          <1> 	call	maknod
  3809                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3810                              <1> ;sysclose_sysret: ; 26/02/2022
  3811 00003FA0 E942FBFFFF          <1> 	jmp	sysret
  3812                              <1>         	;br sysret2 /
  3813                              <1> dir_exists:
  3814                              <1> 	; 14/05/2015
  3815 00003FA5 C705[A16F0000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3815 00003FAD 0000                <1>
  3816 00003FAF E913FBFFFF          <1> 	jmp	error
  3817                              <1> dir_access_err:
  3818                              <1> 	; 14/05/2015
  3819 00003FB4 C705[A16F0000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3819 00003FBC 0000                <1>
  3820 00003FBE E904FBFFFF          <1> 	jmp	error
  3821                              <1> 
  3822                              <1> sysclose: ;<close file>
  3823                              <1> 	; 26/02/2022
  3824                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3825                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3826                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3827                              <1> 	;
  3828                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3829                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3830                              <1> 	; is put in r1 and 'fclose' is called.
  3831                              <1> 	;
  3832                              <1> 	; Calling sequence:
  3833                              <1> 	;	sysclose
  3834                              <1> 	; Arguments:
  3835                              <1> 	;	-  
  3836                              <1> 	; Inputs: *u.r0 - file descriptor
  3837                              <1> 	; Outputs: -
  3838                              <1> 	; ...............................................................
  3839                              <1> 	;				
  3840                              <1> 	; Retro UNIX 8086 v1 modification:
  3841                              <1> 	;	 The user/application program puts file descriptor
  3842                              <1> 	;        in BX register as 'sysclose' system call argument.
  3843                              <1> 	; 	 (argument transfer method 1)
  3844                              <1> 
  3845                              <1> 	; / close the file
  3846                              <1> 	
  3847 00003FC3 89D8                <1> 	mov 	eax, ebx
  3848 00003FC5 E896090000          <1> 	call 	fclose
  3849                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3850                              <1> 		; jsr r0,fclose / close the file
  3851                              <1>                	; br error2 / unknown file descriptor
  3852                              <1> 		; br sysret2
  3853                              <1> 	; 14/05/2015
  3854                              <1> 	;jnc	sysret
  3855                              <1> 	; 04/12/2021
  3856 00003FCA 7205                <1> 	jc	short sysclose_err
  3857 00003FCC E916FBFFFF          <1> 	jmp	sysret
  3858                              <1> 	; 26/02/2022
  3859                              <1> 	;jnc	short sysclose_sysret
  3860                              <1> sysclose_err:
  3861 00003FD1 C705[A16F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3861 00003FD9 0000                <1>
  3862 00003FDB E9E7FAFFFF          <1> 	jmp	error
  3863                              <1> 
  3864                              <1> sysemt:
  3865                              <1> 	; 26/02/2022
  3866                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3867                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3868                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3869                              <1> 	;
  3870                              <1> 	; Retro UNIX 8086 v1 modification: 
  3871                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3872                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3873                              <1> 	;
  3874                              <1> 	; Retro UNIX 8086 v1 feature only!
  3875                              <1> 	;	Using purpose: Kernel will start without time-out
  3876                              <1> 	;	(internal clock/timer) functionality.
  3877                              <1> 	;	Then etc/init will enable clock/timer for
  3878                              <1> 	;	multi tasking. (Then it will not be disabled again
  3879                              <1> 	;	except hardware reset/restart.)
  3880                              <1> 	;
  3881                              <1> 
  3882 00003FE0 803D[986F0000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3883                              <1> 	;;ja	error
  3884                              <1> 	;ja	badsys ; 14/05/2015
  3885                              <1> 	; 24/12/2021
  3886 00003FE7 7605                <1> 	jna	short emt_0 
  3887 00003FE9 E98BFBFFFF          <1> 	jmp	badsys
  3888                              <1> emt_0:
  3889                              <1> 	; 24/12/2021
  3890                              <1> 	;cli
  3891 00003FEE 21DB                <1> 	and	ebx, ebx
  3892 00003FF0 7429                <1> 	jz	short emt_2
  3893                              <1> 	; Enable multi tasking -time sharing-
  3894 00003FF2 B8[994F0000]        <1> 	mov	eax, clock
  3895                              <1> 	; 26/02/2022
  3896 00003FF7 BA[4B0A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3897                              <1> emt_1:
  3898 00003FFC A3[10070000]        <1> 	mov	[x_timer], eax
  3899                              <1> 	; 26/02/2022 (Temporary)
  3900 00004001 8915[14070000]      <1> 	mov	[x_rtci], edx
  3901 00004007 B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3902 00004009 E851020000          <1> 	call	wttyc  ; clear video page
  3903 0000400E B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3904 00004010 E84A020000          <1> 	call	wttyc  ; clear video page
  3905                              <1> 	;
  3906 00004015 FB                  <1> 	sti
  3907 00004016 E9CCFAFFFF          <1> 	jmp	sysret
  3908                              <1> emt_2:
  3909                              <1> 	; Disable multi tasking -time sharing-
  3910 0000401B B8[1C070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3911                              <1> 	; 26/02/2022
  3912 00004020 BA[520A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3913                              <1> 	;
  3914 00004025 EBD5                <1> 	jmp	short emt_1
  3915                              <1> 
  3916                              <1> 	; Original UNIX v1 'sysemt' routine
  3917                              <1> ;sysemt:
  3918                              <1>         ;
  3919                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3920                              <1> 			 ; / in loc 30
  3921                              <1>         ;cmp    30,$core / was the argument a lower address 
  3922                              <1> 			; / than core
  3923                              <1>         ;blo    1f / yes, rtssym
  3924                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3925                              <1> 			; / and less than "ecore"
  3926                              <1>         ;blo    2f / yes, sysret2
  3927                              <1> ;1:
  3928                              <1>         ;mov    $rtssym,30
  3929                              <1> ;2:
  3930                              <1>         ;br     sysret2
  3931                              <1> 
  3932                              <1> sysilgins:
  3933                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3934                              <1> 	; 03/06/2013
  3935                              <1> 	; Retro UNIX 8086 v1 modification: 
  3936                              <1> 	;	not a valid system call ! (not in use)
  3937                              <1> 	;
  3938 00004027 E94DFBFFFF          <1> 	jmp	badsys
  3939                              <1> 	;jmp	error
  3940                              <1> 	;;jmp 	sysret
  3941                              <1> 
  3942                              <1> 	; Original UNIX v1 'sysemt' routine
  3943                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3944                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3945                              <1> 			  ;/ put it in loc 8.,
  3946                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3947                              <1> 		       ; / trap address
  3948                              <1>         ;blo    1f / is the address a user core address?  
  3949                              <1> 		; / yes, go to 2f
  3950                              <1>         ;cmp    10,$ecore
  3951                              <1>         ;blo    2f
  3952                              <1> ;1:
  3953                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3954                              <1> 		    ; / instruction trap address for the system
  3955                              <1> ;2:
  3956                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3957                              <1> 
  3958                              <1> sysmdate: ; < change the modification time of a file >
  3959                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3960                              <1> 	;	(ECX input)
  3961                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3962                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3963                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3964                              <1> 	;
  3965                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3966                              <1> 	; file into core. The user is checked if he is the owner 
  3967                              <1> 	; or super user. If he is neither an error occurs.
  3968                              <1> 	; 'setimod' is then called to set the i-node modification
  3969                              <1> 	; byte and the modification time, but the modification time
  3970                              <1> 	; is overwritten by whatever get put on the stack during
  3971                              <1> 	; a 'systime' system call. This calls are restricted to
  3972                              <1> 	; the super user.		
  3973                              <1> 	;
  3974                              <1> 	; Calling sequence:
  3975                              <1> 	;	sysmdate; name
  3976                              <1> 	; Arguments:
  3977                              <1> 	;	name - points to the name of file
  3978                              <1> 	; Inputs: (arguments)
  3979                              <1> 	; Outputs: -
  3980                              <1> 	; ...............................................................
  3981                              <1> 	;				
  3982                              <1> 	; Retro UNIX 8086 v1 modification: 
  3983                              <1> 	;	 The user/application program puts address 
  3984                              <1> 	;	 of the file name in BX register 
  3985                              <1> 	;	 as 'sysmdate' system call argument.
  3986                              <1> 	;
  3987                              <1> ; / change the modification time of a file
  3988                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3989 0000402C 891D[646F0000]      <1>         mov	[u.namep], ebx
  3990                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  3991 00004032 890D[D06B0000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  3992 00004038 E897090000          <1> 	call	namei
  3993                              <1> 		; jsr r0,namei / get its i-number
  3994                              <1> 	;;jc	error       
  3995                              <1> 	;	; br error2 / no, such file
  3996                              <1> 	;jc	fnotfound ; file not found !
  3997                              <1> 	; 24/12/2021
  3998 0000403D 7305                <1> 	jnc	short mdate_0
  3999 0000403F E99BFEFFFF          <1> 	jmp	fnotfound
  4000                              <1> mdate_0:
  4001 00004044 E89B110000          <1> 	call	iget
  4002                              <1> 		; jsr r0,iget / get i-node into core
  4003 00004049 A0[986F0000]        <1> 	mov	al, [u.uid]
  4004 0000404E 3A05[4B6C0000]      <1> 	cmp	al, [i.uid]
  4005                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  4006 00004054 7413                <1> 	je	short mdate_1
  4007                              <1>         	; beq 1f / yes
  4008 00004056 20C0                <1> 	and	al, al
  4009                              <1> 		; tstb u.uid / no, is user the super user
  4010                              <1> 	;jnz	error
  4011                              <1> 		; bne error2 / no, error
  4012 00004058 740F                <1> 	jz	short mdate_1
  4013 0000405A C705[A16F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  4013 00004062 0000                <1>
  4014                              <1> sysstty_err:	; 04/02/2022
  4015 00004064 E95EFAFFFF          <1> 	jmp	error
  4016                              <1> mdate_1: ;1:
  4017 00004069 E880120000          <1> 	call	setimod
  4018                              <1>         	; jsr r0,setimod / fill in modification data,
  4019                              <1> 		               ; / time etc.
  4020 0000406E BE[D06B0000]        <1> 	mov	esi, p_time
  4021 00004073 BF[626C0000]        <1> 	mov	edi, i.mtim
  4022 00004078 A5                  <1> 	movsd
  4023                              <1> 		; mov 4(sp),i.mtim / move present time to
  4024                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  4025 00004079 E969FAFFFF          <1>         jmp	sysret
  4026                              <1> 		; br sysret2
  4027                              <1> 
  4028                              <1> 	; 04/02/2022
  4029                              <1> sysstty_err_s:
  4030 0000407E 880D[4C6F0000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  4031 00004084 EBDE                <1> 	jmp	short sysstty_err
  4032                              <1> 
  4033                              <1> sysstty: ; < set tty status and mode >
  4034                              <1> 	; 26/02/2022
  4035                              <1> 	; 04/02/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4036                              <1> 	; 02/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  4037                              <1> 	; 01/02/2022 (Retro UNIX 386 v1) -clear screen-
  4038                              <1> 	; 17/11/2015
  4039                              <1> 	; 12/11/2015
  4040                              <1> 	; 29/10/2015
  4041                              <1> 	; 17/10/2015
  4042                              <1> 	; 13/10/2015
  4043                              <1> 	; 29/06/2015
  4044                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4045                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4046                              <1> 	;
  4047                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4048                              <1> 	; whose file descriptor is in (u.r0).
  4049                              <1> 	;
  4050                              <1> 	; Calling sequence:
  4051                              <1> 	;	sysstty; arg
  4052                              <1> 	; Arguments:
  4053                              <1> 	;	arg - address of 3 consequitive words that contain
  4054                              <1> 	;	      the source of status data	
  4055                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4056                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4057                              <1> 	; ...............................................................
  4058                              <1> 	;	
  4059                              <1> 	; Retro UNIX 8086 v1 modification: 
  4060                              <1> 	;	'sysstty' system call will set the tty
  4061                              <1> 	;	(clear keyboard buffer and set cursor position)
  4062                              <1> 	;	 in following manner:
  4063                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4064                              <1> 	;
  4065                              <1> 	; Inputs:
  4066                              <1> 	;	BX = 0 --> means
  4067                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4068                              <1> 	;	      set cursor position for console tty, only 
  4069                              <1> 	;	      CH will be ignored (char. will not be written)	
  4070                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4071                              <1> 	;	      set console tty for (current) process
  4072                              <1> 	;	      CL = tty number (0 to 9)
  4073                              <1> 	;	      (If CH = 0, character will not be written)			
  4074                              <1> 	;          If CH > 0 (CL < FFh)	
  4075                              <1> 	;             CL = tty number (0 to 9)
  4076                              <1> 	;	      CH = character will be written
  4077                              <1> 	;	        at requested cursor position (in DX)	
  4078                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4079                              <1>   	;		(only tty number 0 to 7) 
  4080                              <1> 	;          DL = communication parameters (for serial ports) 
  4081                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4082                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4083                              <1> 	;			or set cursor position	
  4084                              <1> 	;	   DH = 0FFh -> DL is not valid
  4085                              <1> 	;		do not set serial port parameters 
  4086                              <1> 	;		or do not set cursor position
  4087                              <1> 	;
  4088                              <1> 	;	BX > 0 --> points to name of tty
  4089                              <1> 	;    	   CH > 0 -->
  4090                              <1> 	;		CH = character will be written in current 
  4091                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4092                              <1> 	;	     	or character will be sent to serial port
  4093                              <1> 	;	     	(for tty number 8 or 9)
  4094                              <1> 	;		CL = color of the character if tty number < 8.
  4095                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4096                              <1> 	;		set mode (tty 8 to 9) or 
  4097                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4098                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4099                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4100                              <1> 	;		(DL is not valid)
  4101                              <1> 	;	   DL = communication parameters 
  4102                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4103                              <1> 	;
  4104                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4105                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4106                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4107                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4108                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4109                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4110                              <1> 	;
  4111                              <1> 	; Outputs:
  4112                              <1> 	;	cf = 0 -> OK
  4113                              <1> 	;	     AL = tty number (0 to 9)
  4114                              <1> 	;	     AH = line status if tty number is 8 or 9
  4115                              <1> 	;	     AH = process number (of the caller) 	
  4116                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4117                              <1> 	;	     AH = FFh if the tty is locked 
  4118                              <1> 	;		  (owned by another process)
  4119                              <1> 	;	        = process number (of the caller) 
  4120                              <1> 	;		  (if < FFh and tty number < 8)
  4121                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4122                              <1> 	;	     AH = line status if tty number is 8 or 9
  4123                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4124                              <1> 	;	
  4125                              <1> 
  4126                              <1> 	; 27/06/2015 (32 bit modifications)
  4127                              <1> 	; 14/01/2014
  4128 00004086 31C0                <1> 	xor 	eax, eax
  4129 00004088 6648                <1> 	dec	ax ; 17/10/2015
  4130 0000408A A3[4C6F0000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4131                              <1> 	;;;
  4132                              <1> 	; 01/02/2022
  4133 0000408F FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4134 00004091 39C2                <1> 	cmp	edx, eax
  4135                              <1> 	;cmp	dx, ax ; 0FFFFh
  4136 00004093 7521                <1> 	jne	short sysstty_18
  4137                              <1> 	; clear video page
  4138                              <1> 	; (CH must be 0)
  4139 00004095 08ED                <1> 	or	ch, ch
  4140 00004097 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4141 00004099 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4142 0000409C 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4143 0000409E 20C9                <1> 	and	cl, cl
  4144 000040A0 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4145 000040A2 0FB635[9B6F0000]    <1> 	movzx	esi, byte [u.uno]
  4146 000040A9 8A8E[A76C0000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4147 000040AF 80F907              <1> 	cmp	cl, 7
  4148 000040B2 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4149                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4150 000040B4 FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4151                              <1> sysstty_18:
  4152 000040B6 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4153                              <1> 	; cl = video page (tty) number		
  4154                              <1> 	;;;
  4155 000040B8 21DB                <1> 	and	ebx, ebx
  4156                              <1> 	;jnz	sysstty_6
  4157                              <1> 	; 01/02/2022
  4158 000040BA 7405                <1> 	jz	short sysstty_19
  4159 000040BC E9C2000000          <1> 	jmp	sysstty_6
  4160                              <1> sysstty_19:
  4161                              <1> 	; set console tty
  4162                              <1> 	; 29/10/2015
  4163                              <1> 	; 17/01/2014 
  4164 000040C1 80F909              <1> 	cmp	cl, 9
  4165 000040C4 7613                <1> 	jna	short sysstty_0
  4166                              <1> 	; 17/11/2015
  4167 000040C6 80F9FF              <1> 	cmp	cl, 0FFh
  4168 000040C9 7202                <1> 	jb	short sysstty_13
  4169 000040CB 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4170                              <1> sysstty_13:
  4171 000040CD 8A1D[9B6F0000]      <1> 	mov	bl, [u.uno] ; process number
  4172 000040D3 8A8B[A76C0000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4173                              <1> sysstty_0:
  4174                              <1> 	; 29/06/2015
  4175                              <1> 	;push	dx
  4176                              <1> 	;push	cx
  4177                              <1> 	; 01/02/2022
  4178 000040D9 52                  <1> 	push	edx
  4179 000040DA 51                  <1> 	push	ecx
  4180 000040DB 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4181 000040DD 88C8                <1> 	mov	al, cl
  4182 000040DF A2[4C6F0000]        <1> 	mov	[u.r0], al ; tty number (0 to 9)
  4183 000040E4 E87A190000          <1> 	call	ottyp
  4184                              <1> 	; 01/02/2022
  4185 000040E9 59                  <1> 	pop	ecx
  4186 000040EA 5A                  <1> 	pop	edx
  4187                              <1> 	;pop	cx
  4188                              <1> 	;pop	dx
  4189                              <1> 	;
  4190 000040EB 7220                <1> 	jc	short sysstty_pd_err
  4191                              <1> 	;
  4192                              <1> 	; 26/02/2022 (Bug! BugFix)
  4193                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4194                              <1> 	;
  4195 000040ED 80F908              <1> 	cmp	cl, 8
  4196 000040F0 720C                <1> 	jb	short sysstty_2
  4197                              <1> 	;
  4198 000040F2 80FEFF              <1> 	cmp	dh, 0FFh
  4199 000040F5 7407                <1> 	je	short sysstty_2
  4200                              <1> 		; set communication parameters for serial ports
  4201                              <1> 
  4202                              <1> ; 01/02/2022
  4203                              <1> ;	; 29/10/2015
  4204                              <1> ;	mov	ah, dl ; communication parameters
  4205                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4206                              <1> ;		;			 THRE int + RDA int 
  4207                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4208                              <1> ;		;			 THRE int + RDA int 
  4209                              <1> ;	sub	al, al ; 0
  4210                              <1> ;	; 12/07/2014
  4211                              <1> ;	cmp	cl, 9
  4212                              <1> ;	jb	short sysstty_1
  4213                              <1> ;	inc	al
  4214                              <1> ;sysstty_1:
  4215                              <1> ;	; 01/02/2022
  4216                              <1> ;	push	ecx
  4217                              <1> ;	;push	cx
  4218                              <1> ;	; 29/06/2015	
  4219                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4220                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4221                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4222                              <1> ;	; 01/02/2022
  4223                              <1> ;	pop	ecx	
  4224                              <1> ;	;pop	cx
  4225                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4226                              <1> 
  4227                              <1> 	; 01/02/2022
  4228 000040F7 E830010000          <1> 	call	sysstty_scp
  4229 000040FC 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4230                              <1> 
  4231                              <1> sysstty_2:
  4232                              <1> 	; 17/01/2014
  4233 000040FE 20ED                <1> 	and	ch, ch 	; set cursor position 
  4234                              <1> 			; or comm. parameters ONLY
  4235 00004100 7527                <1> 	jnz	short sysstty_3
  4236                              <1> 	; 01/02/2022
  4237 00004102 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4238 00004106 7214                <1> 	jb	short sysstty_20
  4239                              <1> 	; clear screen (video page)
  4240 00004108 E93B010000          <1> 	jmp	sysstty_14
  4241                              <1> 
  4242                              <1> sysstty_pd_err: ; 29/06/2015
  4243                              <1> 	; 'permission denied !' error
  4244 0000410D C705[A16F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4244 00004115 0000                <1>
  4245 00004117 E9ABF9FFFF          <1> 	jmp	error
  4246                              <1> 
  4247                              <1> sysstty_20:
  4248 0000411C 0FB61D[9B6F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4249 00004123 888B[A76C0000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4250                              <1> sysstty_3:
  4251                              <1> 	; 16/01/2014
  4252 00004129 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4253                              <1> 	; 17/11/2015
  4254 0000412B B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4255 0000412D 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4256                              <1> 	;jna	sysstty_9
  4257                              <1> 	; 01/02/2022
  4258 0000412F 7705                <1> 	ja	short sysstty_12
  4259 00004131 E9C5000000          <1> 	jmp	sysstty_9
  4260                              <1> 
  4261                              <1> sysstty_12:
  4262                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4263                              <1> 	; (Set specified serial port as console tty port)
  4264                              <1> 	; CH = character to be written
  4265                              <1> 	; 15/04/2014
  4266                              <1> 	; CH = 0 --> initialization only
  4267                              <1> 	; AL = character
  4268                              <1> 	; 26/06/2014
  4269 00004136 880D[A06F0000]      <1> 	mov	[u.ttyn], cl
  4270                              <1> 	; 12/07/2014
  4271 0000413C 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4272                              <1> 	; 02/02/2022
  4273 0000413E FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4274 00004140 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4275 00004142 FEC8                <1> 	dec	al  ; 1 -> 0	
  4276                              <1> 	;and	al, al
  4277 00004144 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4278                              <1>  	; 04/07/2014
  4279 00004146 E8541F0000          <1> 	call 	sndc
  4280                              <1> 	; 12/07/2014
  4281 0000414B EB0C                <1> 	jmp	short sysstty_5
  4282                              <1> 
  4283                              <1> sysstty_4:
  4284                              <1> 	; 12/07/2014
  4285                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4286 0000414D 88E0                <1> 	mov	al, ah ; 29/06/2015
  4287 0000414F 2C08                <1> 	sub	al, 8
  4288                              <1> 	; 27/06/2015
  4289 00004151 E824F4FFFF          <1> 	call	sp_status ; get serial port status
  4290                              <1> 	; AL = Line status, AH = Modem status
  4291                              <1> 	; 12/11/2015
  4292 00004156 3C80                <1> 	cmp	al, 80h
  4293 00004158 F5                  <1> 	cmc
  4294                              <1> sysstty_5:
  4295 00004159 66A3[4D6F0000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4296                              <1> 		; EAX bits 16-23 = modem status	
  4297 0000415F 9C                  <1> 	pushf
  4298 00004160 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4299 00004162 A0[A06F0000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4300 00004167 E81A1A0000          <1> 	call	cttyp
  4301 0000416C 9D                  <1> 	popf
  4302                              <1> 	;jnc	sysret ; time out error 
  4303                              <1> 	; 01/02/2022
  4304 0000416D 7205                <1> 	jc	short sysstty_tmout_err
  4305 0000416F E973F9FFFF          <1> 	jmp	sysret
  4306                              <1> 
  4307                              <1> sysstty_tmout_err:
  4308 00004174 C705[A16F0000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4308 0000417C 0000                <1>
  4309 0000417E E944F9FFFF          <1> 	jmp	error
  4310                              <1> 
  4311                              <1> sysstty_6:
  4312                              <1> 	;push	dx
  4313                              <1> 	;push	cx
  4314                              <1> 	; 01/02/2022
  4315 00004183 52                  <1> 	push	edx
  4316 00004184 51                  <1> 	push	ecx
  4317 00004185 891D[646F0000]      <1> 	mov	[u.namep], ebx
  4318 0000418B E844080000          <1> 	call	namei
  4319                              <1> 	; 01/02/2022
  4320 00004190 59                  <1> 	pop	ecx
  4321 00004191 5A                  <1> 	pop	edx
  4322                              <1> 	;pop	cx
  4323                              <1> 	;pop	dx
  4324 00004192 7258                <1> 	jc	short sysstty_inv_dn
  4325                              <1> 	;
  4326 00004194 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4327 00004198 7752                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4328                              <1> 	;
  4329 0000419A 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4330                              <1> 		       ; /dev/COM1, /dev/COM2
  4331 0000419C 7204                <1> 	jb	short sysstty_7
  4332 0000419E 2C0A                <1> 	sub	al, 10
  4333 000041A0 EB11                <1> 	jmp	short sysstty_8
  4334                              <1> 
  4335                              <1> sysstty_7:
  4336 000041A2 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4337 000041A4 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4338 000041A6 0FB61D[9B6F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4339 000041AD 8A83[A76C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4340                              <1> sysstty_8:
  4341                              <1> 	; 26/02/2022
  4342                              <1> 	; (ebx < 256)	
  4343 000041B3 A2[4C6F0000]        <1> 	mov	[u.r0], al
  4344                              <1> 	; 01/02/2022
  4345                              <1> 	;push	dx
  4346                              <1> 	;push	ax
  4347                              <1> 	;push	cx
  4348 000041B8 52                  <1> 	push	edx
  4349 000041B9 50                  <1> 	push	eax
  4350 000041BA 51                  <1> 	push	ecx	
  4351 000041BB E8A3180000          <1> 	call	ottyp
  4352 000041C0 59                  <1> 	pop	ecx
  4353 000041C1 58                  <1> 	pop	eax
  4354 000041C2 5A                  <1> 	pop	edx
  4355                              <1> 	;pop	cx
  4356                              <1> 	;pop	ax
  4357                              <1> 	;pop	dx
  4358                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4359                              <1> 	; 01/02/2022
  4360 000041C3 7305                <1> 	jnc	short sysstty_21
  4361 000041C5 E943FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4362                              <1> sysstty_21:
  4363                              <1> 	; 29/10/2015
  4364 000041CA 86E9                <1> 	xchg 	ch, cl
  4365                              <1> 		; cl = character, ch = color code
  4366 000041CC 86C1                <1> 	xchg	al, cl
  4367                              <1> 		; al = character, cl = tty number
  4368 000041CE 80F907              <1> 	cmp	cl, 7
  4369                              <1> 	;ja	sysstty_12
  4370                              <1> 	; 01/02/2022
  4371 000041D1 7628                <1> 	jna	short sysstty_16
  4372                              <1> ;;
  4373 000041D3 80FEFF              <1> 	cmp	dh, 0FFh
  4374 000041D6 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4375                              <1> 
  4376                              <1> ; 01/02/2022
  4377                              <1> ;	; 29/10/2015
  4378                              <1> ;	mov	ah, dl ; communication parameters
  4379                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4380                              <1> ;		;			 THRE int + RDA int 
  4381                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4382                              <1> ;		;			 THRE int + RDA int 
  4383                              <1> ;	sub	al, al ; 0
  4384                              <1> ;	; 12/07/2014
  4385                              <1> ;	cmp	cl, 9
  4386                              <1> ;	jb	short sysstty_1
  4387                              <1> ;	inc	al
  4388                              <1> ;sysstty_1:
  4389                              <1> ;	; 01/02/2022
  4390                              <1> ;	push	ecx
  4391                              <1> ;	;push	cx
  4392                              <1> ;	; 29/06/2015	
  4393                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4394                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4395                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4396                              <1> ;	; 01/02/2022
  4397                              <1> ;	pop	ecx	
  4398                              <1> ;	;pop	cx
  4399                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4400                              <1> 
  4401                              <1> 	; 02/02/2022
  4402 000041D8 88C5                <1> 	mov	ch, al ; save char
  4403                              <1> 	; 01/02/2022
  4404 000041DA E84D000000          <1> 	call	sysstty_scp
  4405 000041DF 7293                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4406                              <1> 	; 02/02/2022
  4407 000041E1 88E8                <1> 	mov	al, ch ; restore char
  4408                              <1> sysstty_22:
  4409                              <1> 	; 01/02/2022
  4410 000041E3 08ED                <1> 	or	ch, ch
  4411 000041E5 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4412                              <1> 	; send char to (serial port) terminal
  4413                              <1> 	; al = character
  4414                              <1> 	; cl = tty number (8 or 9)
  4415 000041E7 E94AFFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4416                              <1> 
  4417                              <1> sysstty_inv_dn: 
  4418                              <1> 	; 27/06/2015
  4419                              <1> 	; Invalid device name (not a tty) ! error
  4420                              <1> 	; (Device is not a tty or device name not found)
  4421 000041EC C705[A16F0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4421 000041F4 0000                <1>
  4422 000041F6 E9CCF8FFFF          <1> 	jmp	error 
  4423                              <1> 
  4424                              <1> sysstty_16:
  4425                              <1> 	; 26/02/2022
  4426                              <1> 	; 16/01/2014
  4427                              <1> 	;xor	bh, bh
  4428                              <1> 	; 02/02/2022
  4429                              <1> sysstty_9: 	; tty 0 to tty 7
  4430                              <1> 	; al = character
  4431                              <1> 	; ch = color/attribute ; 01/02/2022
  4432                              <1> 	;
  4433                              <1> 	; 26/02/2022 (BugFix)
  4434                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4435 000041FB 29DB                <1> 	sub	ebx, ebx ; *
  4436 000041FD 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4437 00004200 740B                <1> 	je	short sysstty_10
  4438                              <1> 	; 02/02/2022
  4439 00004202 51                  <1> 	push	ecx
  4440 00004203 50                  <1> 	push	eax
  4441                              <1> 	;push	cx
  4442                              <1> 	;push	ax	
  4443                              <1> 	;movzx	ebx, cl
  4444 00004204 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4445 00004206 E8C4D2FFFF          <1> 	call	set_cpos
  4446                              <1> 	;pop	ax
  4447                              <1> 	;pop	cx
  4448                              <1> 	; 02/02/2022
  4449 0000420B 58                  <1> 	pop	eax
  4450 0000420C 59                  <1> 	pop	ecx
  4451                              <1> sysstty_10: 
  4452                              <1> 	; 29/10/2015
  4453 0000420D 08C0                <1> 	or	al, al ; character
  4454 0000420F 740D                <1> 	jz      short sysstty_11 ; al = 0
  4455                              <1> 	; 17/11/2015
  4456 00004211 3CFF                <1> 	cmp	al, 0FFh
  4457 00004213 7309                <1> 	jnb	short sysstty_11
  4458                              <1> 		; ch > 0 and ch < FFh
  4459                              <1> 	; write a character at current cursor position
  4460 00004215 88EC                <1> 	mov	ah, ch ; color/attribute
  4461                              <1> 	; 12/07/2014
  4462                              <1> 	;push	cx
  4463                              <1> 	; 02/02/2022
  4464 00004217 51                  <1> 	push	ecx
  4465 00004218 E89ED3FFFF          <1> 	call	write_c_current
  4466                              <1> 	;pop	cx
  4467                              <1> 	; 02/02/2022
  4468 0000421D 59                  <1> 	pop	ecx
  4469                              <1> sysstty_11:
  4470                              <1> 	; 14/01/2014
  4471 0000421E 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4472                              <1> 	; 18/01/2014
  4473                              <1> 	;movzx	eax, cl ; 27/06/2015
  4474 00004220 88C8                <1> 	mov	al, cl
  4475 00004222 E85F190000          <1> 	call	cttyp
  4476 00004227 E9BBF8FFFF          <1> 	jmp	sysret
  4477                              <1> 
  4478                              <1> sysstty_scp:
  4479                              <1> 	; 02/02/2022
  4480                              <1> 	; set communication parameters (for COM1 or COM2)
  4481                              <1> 	; 01/02/2022
  4482                              <1> 	;
  4483                              <1> 	; 29/10/2015
  4484 0000422C 88D4                <1> 	mov	ah, dl ; communication parameters
  4485                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4486                              <1> 		;			 THRE int + RDA int 
  4487                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4488                              <1> 		;			 THRE int + RDA int 
  4489 0000422E 28C0                <1> 	sub	al, al ; 0
  4490                              <1> 	; 12/07/2014
  4491 00004230 80F909              <1> 	cmp	cl, 9
  4492 00004233 7202                <1> 	jb	short sysstty_1
  4493 00004235 FEC0                <1> 	inc	al
  4494                              <1> sysstty_1:
  4495                              <1> 	; 02/02/2022
  4496 00004237 52                  <1> 	push	edx
  4497                              <1> 	; 01/02/2022
  4498 00004238 51                  <1> 	push	ecx
  4499                              <1> 	;push	cx
  4500                              <1> 	; 29/06/2015	
  4501 00004239 E844F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4502 0000423E 66890D[4D6F0000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4503                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4504                              <1> 	; 01/02/2022
  4505 00004245 59                  <1> 	pop	ecx	
  4506                              <1> 	;pop	cx
  4507 00004246 5A                  <1> 	pop	edx ; 02/02/2022
  4508                              <1> 	; 01/02/2022
  4509                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4510 00004247 C3                  <1> 	retn
  4511                              <1> 
  4512                              <1> sysstty_14:
  4513                              <1> 	; 26/02/2022
  4514                              <1> 	; 02/02/2022
  4515                              <1> 	; ch = 0
  4516                              <1> 	; cl = video page
  4517                              <1> 	;
  4518                              <1> 	; dx = 0FFFFh
  4519                              <1> 	; clear screen (video page)
  4520                              <1> 	;
  4521                              <1> 
  4522                              <1> 	; 02/02/2022
  4523                              <1> 	; clear screen
  4524                              <1> 	;
  4525                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4526                              <1> 	; clear video page
  4527                              <1> 
  4528                              <1> 	; 26/02/2022
  4529 00004248 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4530                              <1> 
  4531                              <1> 	; clear video page
  4532 0000424A E810000000          <1> 	call	wttyc ; 26/02/2022
  4533                              <1> 
  4534                              <1> 	; 26/02/2022
  4535 0000424F 88D8                <1> 	mov	al, bl
  4536 00004251 8A25[9B6F0000]      <1> 	mov	ah, [u.uno]
  4537 00004257 66A3[4C6F0000]      <1> 	mov	[u.r0], ax
  4538 0000425D EBBF                <1> 	jmp	short sysstty_11
  4539                              <1> 
  4540                              <1> vp_clr:	; 27/02/2022
  4541                              <1> wttyc:
  4542                              <1> 	; 23/02/2022
  4543                              <1> 	; (clear video page)
  4544                              <1> 	; INPUT:
  4545                              <1> 	;  bl = video page (0 to 7)
  4546                              <1> 	;
  4547                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4548                              <1> 
  4549                              <1> 	;xor	dx, dx ; column 0, row 0
  4550                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4551                              <1> 	;
  4552                              <1> ;	movzx	ebx, cl
  4553                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4554                              <1> 
  4555                              <1> ;	shl 	bl, 1 
  4556                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4557                              <1> ;		; AL = lock value (0 or process number)
  4558                              <1> ;	or	al, al
  4559                              <1> ;	jz	short @f
  4560                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4561                              <1> ;	jne	short sysstty_15
  4562                              <1> ;		; only the owner can clear its video page
  4563                              <1> ;	xor	al, al ; 0
  4564                              <1> ;@@:
  4565                              <1> ;	;mov	bl, cl		
  4566                              <1> ;	shr	bl, 1 
  4567                              <1> 
  4568 0000425F 30C0                <1> 	xor	al, al	; 0
  4569 00004261 B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4570                              <1> 
  4571                              <1> 	; scroll_up input:
  4572                              <1> 	;
  4573                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4574                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4575                              <1> 	; ah = attribute to be used on blanked line
  4576                              <1> 	; bl = video page number (0 to 7)
  4577                              <1> 
  4578 00004263 E8F1D2FFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4579                              <1> 
  4580                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4581                              <1> 
  4582                              <1> 	; bl = video page number (0 to 7)
  4583                              <1> 	;xor	dx, dx ; column 0, row 0
  4584                              <1> 	; 02/02/2022
  4585 00004268 31D2                <1> 	xor	edx, edx
  4586                              <1> 	; 26/02/2022
  4587                              <1> 	;call	set_cpos
  4588                              <1> 	;retn
  4589 0000426A E960D2FFFF          <1> 	jmp	set_cpos
  4590                              <1> 
  4591                              <1> 	;mov	al, bl
  4592                              <1> 	;mov	ah, [u.uno]
  4593                              <1> 	;mov	[u.r0], ax
  4594                              <1> 	;jmp	short sysstty_11
  4595                              <1> 
  4596                              <1> ;sysstty_15:
  4597                              <1> ;	; 30/01/2022
  4598                              <1> ;	; permission (denied) error
  4599                              <1> ;	;xor	dl, dl ; sysstty call sign
  4600                              <1> ;	mov	al, cl
  4601                              <1> ;	sub	ah, ah ; 0
  4602                              <1> ;	call	cttyp
  4603                              <1> ;	jmp	error
  4604                              <1> 
  4605                              <1> ; Original UNIX v1 'sysstty' routine:
  4606                              <1> ; gtty:
  4607                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4608                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4609                              <1> 	; 		/ r2 has source
  4610                              <1>         ;mov    r2,-(sp)
  4611                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4612                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4613                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4614                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4615                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4616                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4617                              <1>         ;       br .+4 / list empty, skip branch
  4618                              <1>         ;br     1b / get another character until list is empty
  4619                              <1>         ;mov    0b,r1 / move cc offset to r1
  4620                              <1>         ;inc    r1 / bump it for output clist
  4621                              <1>         ;tstb   cc(r1) / is it 0
  4622                              <1>         ;beq    1f / yes, no characters to output
  4623                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4624                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4625                              <1>         ;br     1b / try to calm it down again
  4626                              <1> ;1:
  4627                              <1>         ;mov    (sp)+,r1
  4628                              <1>         ;mov    (sp)+,r2 / restore registers
  4629                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4630                              <1>         ;beq    1f / if 0, 1f
  4631                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4632                              <1>         ;                   / control status register
  4633                              <1> ;1:
  4634                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4635                              <1>         ;beq    1f / if 0 1f
  4636                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4637                              <1> 	;		    / control status reg
  4638                              <1> ;1:
  4639                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4640                              <1>         ;jmp     sysret2 / return to user
  4641                              <1> 
  4642                              <1> sysgtty: ; < get tty status >
  4643                              <1> 	; 26/02/2022
  4644                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4645                              <1> 	;	    ((32 bit reg push/pop))
  4646                              <1> 	; 23/11/2015
  4647                              <1> 	; 29/10/2015
  4648                              <1> 	; 17/10/2015
  4649                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4650                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4651                              <1> 	;
  4652                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4653                              <1> 	; It stores in the three words addressed by it's argument
  4654                              <1> 	; the status of the typewriter whose file descriptor
  4655                              <1> 	; in (u.r0).
  4656                              <1> 	;
  4657                              <1> 	; Calling sequence:
  4658                              <1> 	;	sysgtty; arg
  4659                              <1> 	; Arguments:
  4660                              <1> 	;	arg - address of 3 words destination of the status
  4661                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4662                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4663                              <1> 	; ...............................................................
  4664                              <1> 	;	
  4665                              <1> 	; Retro UNIX 8086 v1 modification: 
  4666                              <1> 	;	'sysgtty' system call will return status of tty
  4667                              <1> 	;	(keyboard, serial port and video page status)
  4668                              <1> 	;	 in following manner:
  4669                              <1> 	;
  4670                              <1> 	; Inputs:
  4671                              <1> 	;	BX = 0 --> means 
  4672                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4673                              <1> 	;	                 for (current) process
  4674                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4675                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4676                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4677                              <1> 	;	     CH > 0 -->	tty number + 1
  4678                              <1> 	;
  4679                              <1> 	;	BX > 0 --> points to name of tty
  4680                              <1> 	;	     CL = 0 --> return keyboard status
  4681                              <1> 	;	     CL = 1 --> return video page status
  4682                              <1> 	;	     CH = undefined		 
  4683                              <1> 	;
  4684                              <1> 	; Outputs:
  4685                              <1> 	;	cf = 0 ->
  4686                              <1> 	;
  4687                              <1> 	;	     AL = tty number from 0 to 9
  4688                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4689                              <1> 	;	     AH = 0 if the tty is free/unused
  4690                              <1> 	;	     AH = the process number of the caller 
  4691                              <1>  	;	     AH = FFh if the tty is locked by another process
  4692                              <1> 	;
  4693                              <1> 	;	  (if calling is for serial port status)
  4694                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4695                              <1> 	;		  (BH = modem status, BL = Line status)
  4696                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4697                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4698                              <1> 	;
  4699                              <1> 	;	  (if calling is for keyboard status)
  4700                              <1> 	;	     BX = current character in tty/keyboard buffer
  4701                              <1> 	;		  (BH = scan code, BL = ascii code)
  4702                              <1> 	;		  (BX=0 if there is not a waiting character)
  4703                              <1> 	;	     CX  is undefined
  4704                              <1> 	;
  4705                              <1> 	;	  (if calling is for video page status)	
  4706                              <1> 	;	     BX = cursor position on the video page
  4707                              <1> 	;		  if tty number < 8
  4708                              <1> 	;		  (BH = row, BL = column)
  4709                              <1> 	;	     CX = current character (in cursor position)
  4710                              <1> 	;		  on the video page of the tty 
  4711                              <1> 	;		  if tty number < 8
  4712                              <1> 	;		  (CH = color, CL = character)
  4713                              <1> 	;	
  4714                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4715                              <1> 	;
  4716                              <1> 	;	     AH = FFh if the caller is not owner of
  4717                              <1> 	;		  specified tty or console tty
  4718                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4719                              <1> 	;	     BX, CX are undefined if cf = 1
  4720                              <1> 	;
  4721                              <1> 	;	  (If tty number is 8 or 9)
  4722                              <1> 	;	     AL = tty number 
  4723                              <1> 	;	     AH = the process number of the caller 
  4724                              <1> 	;	     BX = serial port status
  4725                              <1> 	;  		 (BH = modem status, BL = Line status)
  4726                              <1> 	;	     CX = 0
  4727                              <1> 	;
  4728                              <1> 		
  4729                              <1> gtty:   ; get (requested) tty number
  4730                              <1> 	; 26/02/2022
  4731                              <1> 	; 17/10/2015
  4732                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4733                              <1> 	; 30/05/2013 - 12/07/2014
  4734                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4735                              <1> 	;
  4736                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4737                              <1> 	;
  4738                              <1> 	; 28/06/2015 (32 bit modifications)
  4739                              <1> 	; 16/01/2014
  4740 0000426F 31C0                <1> 	xor 	eax, eax
  4741 00004271 6648                <1> 	dec	ax ; 17/10/2015
  4742 00004273 A3[4C6F0000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4743 00004278 80F901              <1> 	cmp	cl, 1
  4744 0000427B 760F                <1> 	jna	short sysgtty_0
  4745                              <1> sysgtty_invp:
  4746                              <1> 	; 28/06/2015
  4747 0000427D C705[A16F0000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4747 00004285 0000                <1>
  4748 00004287 E93BF8FFFF          <1> 	jmp	error
  4749                              <1> sysgtty_0:	
  4750 0000428C 21DB                <1> 	and	ebx, ebx
  4751 0000428E 742E                <1> 	jz	short sysgtty_1
  4752                              <1> 	;
  4753 00004290 891D[646F0000]      <1> 	mov	[u.namep], ebx
  4754                              <1> 	;push	cx ; 23/11/2015
  4755 00004296 51                  <1> 	push	ecx ; 24/12/2021
  4756 00004297 E838070000          <1> 	call	namei
  4757 0000429C 59                  <1> 	pop	ecx
  4758                              <1> 	;pop	cx ; 23/11/2015
  4759 0000429D 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4760                              <1> 	;
  4761 0000429F 6683F801            <1> 	cmp	ax, 1
  4762 000042A3 7622                <1> 	jna	short sysgtty_2
  4763                              <1> 	; 26/02/2022
  4764 000042A5 20E4                <1> 	and	ah, ah
  4765 000042A7 7506                <1> 	jnz	short sysgtty_inv_dn
  4766                              <1> 	;sub	ax, 10
  4767 000042A9 2C0A                <1> 	sub	al, 10
  4768 000042AB 3C09                <1> 	cmp	al, 9
  4769                              <1> 	;cmp	ax, 9
  4770                              <1> 	;ja	short sysgtty_inv_dn
  4771                              <1> 	;mov	ch, al
  4772                              <1> 	;jmp	short sysgtty_4
  4773                              <1> 	; 23/11/2015
  4774 000042AD 7629                <1> 	jna	short sysgtty_4
  4775                              <1> sysgtty_inv_dn: 
  4776                              <1> 	; 28/06/2015
  4777                              <1> 	; Invalid device name (not a tty) ! error
  4778                              <1> 	; (Device is not a tty or device name not found)
  4779 000042AF C705[A16F0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4779 000042B7 0000                <1>
  4780 000042B9 E909F8FFFF          <1> 	jmp	error 
  4781                              <1> sysgtty_1:
  4782                              <1> 	; 16/01/2014
  4783 000042BE 80FD0A              <1> 	cmp	ch, 10
  4784 000042C1 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4785 000042C3 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4786 000042C5 790F                <1> 	jns	short sysgtty_3 ; not negative
  4787                              <1> 	;
  4788                              <1> sysgtty_2:
  4789                              <1> 	; get tty number of console tty
  4790 000042C7 8A25[9B6F0000]      <1> 	mov	ah, [u.uno]
  4791                              <1>  	; 28/06/2015
  4792 000042CD 0FB6DC              <1> 	movzx 	ebx, ah
  4793 000042D0 8AAB[A76C0000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4794                              <1> sysgtty_3:
  4795 000042D6 88E8                <1> 	mov	al, ch
  4796                              <1> sysgtty_4:
  4797 000042D8 A2[4C6F0000]        <1> 	mov	[u.r0], al
  4798                              <1>  	; 28/06/2015
  4799                              <1> 	;cmp	al, 9
  4800                              <1> 	;ja	short sysgtty_invp
  4801 000042DD 8B2D[486F0000]      <1> 	mov	ebp, [u.usp]
  4802                              <1> 	; 23/11/2015
  4803 000042E3 20C9                <1> 	and	cl, cl
  4804 000042E5 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4805 000042E7 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4806 000042E9 722E                <1> 	jb	short sysgtty_6 ; video page status
  4807                              <1> 	; serial port status
  4808                              <1> 	; 12/07/2014
  4809                              <1> 	;mov	dx, 0
  4810                              <1> 	;je	short sysgtty_5
  4811                              <1> 	;inc	dl
  4812                              <1> ;sysgtty_5:
  4813                              <1> 	; 28/06/2015
  4814 000042EB 2C08                <1> 	sub	al, 8
  4815 000042ED E888F2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4816                              <1> 	; AL = Line status, AH = Modem status
  4817 000042F2 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4818 000042F6 8A25[9B6F0000]      <1> 	mov	ah, [u.uno]
  4819 000042FC 8825[4D6F0000]      <1>         mov     [u.r0+1], ah
  4820                              <1> 	; 24/12/2021
  4821 00004302 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  4822                              <1> 				; (in ECX)
  4823 00004308 A880                <1> 	test	al, 80h
  4824 0000430A 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4825 0000430C A801                <1> 	test	al, 1
  4826                              <1> 	;jz	sysret
  4827 0000430E 7404                <1> 	jz	short sysgtty_10
  4828 00004310 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  4829                              <1> sysgtty_10:
  4830 00004314 E9CEF7FFFF          <1> 	jmp	sysret
  4831                              <1> sysgtty_6:
  4832 00004319 A2[A06F0000]        <1> 	mov	[u.ttyn], al ; tty number
  4833                              <1> 	;movzx	ebx, al
  4834 0000431E 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4835 00004320 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4836                              <1> 	; 22/04/2014 - 29/06/2015
  4837 00004322 81C3[D46B0000]      <1>         add     ebx, ttyl
  4838 00004328 8A23                <1>  	mov	ah, [ebx]
  4839 0000432A 3A25[9B6F0000]      <1> 	cmp	ah, [u.uno]
  4840 00004330 7404                <1> 	je	short sysgtty_7
  4841 00004332 20E4                <1> 	and	ah, ah
  4842                              <1> 	;jz	short sysgtty_7
  4843 00004334 7506                <1> 	jnz	short sysgtty_8
  4844                              <1> 	;mov	ah, 0FFh
  4845                              <1> sysgtty_7:
  4846 00004336 8825[4D6F0000]      <1>         mov     [u.r0+1], ah
  4847                              <1> sysgtty_8:
  4848 0000433C 08C9                <1> 	or	cl, cl
  4849 0000433E 7510                <1> 	jnz	short sysgtty_9
  4850 00004340 B001                <1> 	mov	al, 1  ; test a key is available
  4851 00004342 E8DB1C0000          <1> 	call	getc
  4852 00004347 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4853 0000434B E997F7FFFF          <1> 	jmp	sysret
  4854                              <1> sysgtty_9:
  4855 00004350 8A1D[A06F0000]      <1> 	mov	bl, [u.ttyn]
  4856                              <1> 	; bl = video page number
  4857 00004356 E8381E0000          <1> 	call 	get_cpos
  4858                              <1> 	; dx = cursor position
  4859 0000435B 66895510            <1> 	mov	[ebp+16], dx ; bx
  4860                              <1> 	;mov	bl, [u.ttyn]
  4861                              <1> 	; bl = video page number
  4862 0000435F E8401E0000          <1> 	call	read_ac_current
  4863                              <1> 	; ax = character and attribute/color
  4864 00004364 66894518            <1> 	mov	[ebp+24], ax ; cx
  4865 00004368 E97AF7FFFF          <1> 	jmp	sysret
  4866                              <1> sysgtty_dnr_err:
  4867                              <1> 	; 'device not responding !' error	
  4868                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4869 0000436D C705[A16F0000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  4869 00004375 0000                <1>
  4870 00004377 E94BF7FFFF          <1> 	jmp	error	
  4871                              <1> 
  4872                              <1> ; Original UNIX v1 'sysgtty' routine:
  4873                              <1> ; sysgtty:
  4874                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4875                              <1> 	;	       / r2 has destination
  4876                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4877                              <1> 	;                     / in 1st word of dest
  4878                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4879                              <1> 	;                     / in 2nd word of dest
  4880                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4881                              <1>         ;jmp    sysret2 / return to user
  4882                              <1> 	
  4883                              <1> ; Original UNIX v1 'gtty' routine:
  4884                              <1> ; gtty:
  4885                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4886                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4887                              <1>         ;jsr    r0,getf / get the i-number of the file
  4888                              <1>         ;tst    r1 / is it open for reading
  4889                              <1>         ;bgt    1f / yes
  4890                              <1>         ;neg    r1 / no, i-number is negative, 
  4891                              <1> 	;          / so make it positive
  4892                              <1> ;1:
  4893                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4894                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4895                              <1>         ;bhis   error9 / no, error
  4896                              <1>         ;asl    r1 / 0%2
  4897                              <1>         ;asl    r1 / 0%4 / yes
  4898                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4899                              <1> 	;	       ; / tty block
  4900                              <1>         ;mov    u.off,r2 / put argument in r2
  4901                              <1>         ;rts    r0 / return
  2101                                  %include 'u2.s'        ; 11/05/2015
  2102                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYS2.INC
  2103                              <1> ; Last Modification: 15/05/2022
  2104                              <1> ; ----------------------------------------------------------------------------
  2105                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2106                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2107                              <1> ;
  2108                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2109                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2110                              <1> ; <Bell Laboratories (17/3/1972)>
  2111                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2112                              <1> ;
  2113                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2114                              <1> ;
  2115                              <1> ; ****************************************************************************
  2116                              <1> 
  2117                              <1> syslink:
  2118                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2119                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2120                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2121                              <1> 	;
  2122                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2123                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2124                              <1> 	; given to the entry that will go in the current directory.
  2125                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2126                              <1> 	; in the name 2 entry of current directory is the same
  2127                              <1> 	; i-number for the name 1 file.
  2128                              <1> 	;
  2129                              <1> 	; Calling sequence:
  2130                              <1> 	;	syslink; name 1; name 2
  2131                              <1> 	; Arguments:
  2132                              <1> 	;	name 1 - file name to which link will be created.
  2133                              <1> 	;	name 2 - name of entry in current directory that
  2134                              <1> 	;		 links to name 1.
  2135                              <1> 	; Inputs: -
  2136                              <1> 	; Outputs: -
  2137                              <1> 	; ...............................................................
  2138                              <1> 	;	
  2139                              <1> 	; Retro UNIX 8086 v1 modification: 
  2140                              <1> 	;       'syslink' system call has two arguments; so,
  2141                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2142                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2143                              <1> 	;
  2144                              <1> 		; / name1, name2
  2145                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2146 0000437C 891D[646F0000]      <1> 	mov	[u.namep], ebx
  2147 00004382 51                  <1> 	push	ecx
  2148 00004383 E84C060000          <1> 	call	namei
  2149                              <1> 		; jsr r0,namei / find the i-number associated with
  2150                              <1> 			     ; / the 1st path name
  2151                              <1>      	;;and	ax, ax
  2152                              <1> 	;;jz	error ; File not found
  2153                              <1> 	;jc	error 
  2154                              <1> 		; br error9 / cannot be found
  2155 00004388 730F                <1> 	jnc	short syslink0
  2156                              <1> 	;pop 	ecx
  2157                              <1> 	; 'file not found !' error
  2158 0000438A C705[A16F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2158 00004392 0000                <1>
  2159 00004394 E92EF7FFFF          <1> 	jmp	error
  2160                              <1> syslink0:
  2161 00004399 E8460E0000          <1> 	call	iget
  2162                              <1> 		; jsr r0,iget / get the i-node into core
  2163 0000439E 8F05[646F0000]      <1> 	pop	dword [u.namep] ; ecx
  2164                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2165                              <1> 	; 24/12/2021
  2166 000043A4 50                  <1> 	push	eax ; *
  2167                              <1> 	;push	ax
  2168                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2169                              <1> 			    ; / (a link to this file is to be created)
  2170                              <1> 	; 24/12/2021
  2171 000043A5 8A0D[2F6F0000]      <1> 	mov	cl, [cdev]
  2172 000043AB 51                  <1> 	push	ecx ; **
  2173                              <1> 	;push	word [cdev]
  2174                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2175 000043AC E852000000          <1> 	call	isdir
  2176                              <1> 		; jsr r0,isdir / is it a directory
  2177 000043B1 E81E060000          <1> 	call	namei
  2178                              <1> 		; jsr r0,namei / no, get i-number of name2
  2179                              <1> 	;jnc	error
  2180                              <1> 		; br .+4   / not found 
  2181                              <1> 			 ; / so r1 = i-number of current directory
  2182                              <1> 			 ; / ii = i-number of current directory
  2183                              <1> 		; br error9 / file already exists., error
  2184 000043B6 720F                <1> 	jc	short syslink1
  2185                              <1> 	; pop eax ; 24/12/2021
  2186                              <1> 	; pop eax
  2187                              <1> 	; 'file exists !' error
  2188 000043B8 C705[A16F0000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2188 000043C0 0000                <1>
  2189 000043C2 E900F7FFFF          <1> 	jmp	error
  2190                              <1> syslink1:
  2191                              <1> 	;pop	cx
  2192                              <1> 	; 24/12/2021
  2193 000043C7 59                  <1> 	pop	ecx ; **
  2194                              <1> 	;cmp	cx, [cdev]
  2195 000043C8 3A0D[2F6F0000]      <1> 	cmp	cl, [cdev]
  2196                              <1> 	;jne	error
  2197                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2198                              <1> 			       ; / end of current directory
  2199                              <1> 	        ; bne error9
  2200 000043CE 740F                <1> 	je	short syslink2
  2201                              <1> 	; 'not same drive !' error
  2202 000043D0 C705[A16F0000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2202 000043D8 0000                <1>
  2203 000043DA E9E8F6FFFF          <1> 	jmp	error
  2204                              <1> syslink2:
  2205                              <1> 	;pop	eax ; 24/12/2021
  2206                              <1> 	;push	eax
  2207                              <1> 	; 24/12/2021
  2208 000043DF 8B0424              <1> 	mov	eax, [esp] ; *
  2209 000043E2 66A3[7E6F0000]      <1> 	mov	[u.dirbuf], ax
  2210                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2211 000043E8 E89E000000          <1> 	call	mkdir
  2212                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2213                              <1> 		 	     ; / in current directory
  2214                              <1> 	; 24/12/2021
  2215 000043ED 58                  <1> 	pop	eax ; *
  2216                              <1> 	;pop	ax
  2217                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2218 000043EE E8F10D0000          <1> 	call	iget
  2219                              <1> 		; jsr r0,iget / get i-node into core
  2220 000043F3 FE05[4A6C0000]      <1> 	inc	byte [i.nlks]
  2221                              <1> 		; incb i.nlks / add 1 to its number of links
  2222 000043F9 E8F00E0000          <1> 	call	setimod
  2223                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2224 000043FE E9E4F6FFFF          <1> 	jmp	sysret
  2225                              <1> 
  2226                              <1> isdir:
  2227                              <1> 	; 03/02/2022
  2228                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2229                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2230                              <1> 	;
  2231                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2232                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2233                              <1> 	;  called by syslink and sysunlink to make sure directories
  2234                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2235                              <1> 	; 'isdir' does not bother checking. The current i-node
  2236                              <1> 	;  is not disturbed.			
  2237                              <1> 	;		
  2238                              <1> 	; INPUTS ->
  2239                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2240                              <1> 	;    u.uid - user id
  2241                              <1> 	; OUTPUTS ->
  2242                              <1> 	;    r1 - contains current i-number upon exit
  2243                              <1> 	;    	 (current i-node back in core) 
  2244                              <1> 	;	
  2245                              <1> 	; ((AX = R1))
  2246                              <1> 	;
  2247                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2248                              <1> 	;
  2249                              <1> 
  2250                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2251                              <1> 	; / there is an error unless super user made the call
  2252                              <1> 	
  2253 00004403 803D[986F0000]00    <1> 	cmp	byte [u.uid], 0 
  2254                              <1> 		; tstb u.uid / super user
  2255 0000440A 762B                <1> 	jna	short isdir1
  2256                              <1> 		; beq 1f / yes, don't care
  2257 0000440C 66FF35[2C6F0000]    <1> 	push	word [ii]
  2258                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2259 00004413 E8CC0D0000          <1> 	call	iget
  2260                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2261                              <1> 	; 03/02/2022
  2262 00004418 F605[496C0000]40    <1> 	test	byte [i.flgs+1], 40h
  2263                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2264                              <1> 		; bit $40000,i.flgs / is it a directory
  2265                              <1> 	;jnz	error
  2266                              <1> 		; bne error9 / yes, error
  2267 0000441F 740F                <1> 	jz	short isdir0
  2268 00004421 C705[A16F0000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2268 00004429 0000                <1>
  2269                              <1> 				; 'permission denied !' error
  2270                              <1> 	; pop	ax
  2271 0000442B E997F6FFFF          <1> 	jmp	error	
  2272                              <1> isdir0:	
  2273 00004430 6658                <1> 	pop	ax
  2274                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2275 00004432 E8AD0D0000          <1> 	call	iget
  2276                              <1> 		; jsr r0,iget / get it back in
  2277                              <1> isdir1: ; 1:
  2278 00004437 C3                  <1> 	retn
  2279                              <1> 		; rts r0
  2280                              <1> 
  2281                              <1> sysunlink:
  2282                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2283                              <1> 	; 04/12/2015 (14 byte file names)
  2284                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2285                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2286                              <1> 	;
  2287                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2288                              <1> 	; name from its directory. If this entry was the last link
  2289                              <1> 	; to the file, the contents of the file are freed and the
  2290                              <1> 	; file is destroyed. If, however, the file was open in any
  2291                              <1> 	; process, the actual destruction is delayed until it is 
  2292                              <1> 	; closed, even though the directory entry has disappeared.
  2293                              <1> 	; 
  2294                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2295                              <1> 	; does not exist or that its directory can not be written.
  2296                              <1> 	; Write permission is not required on the file itself.
  2297                              <1> 	; It is also illegal to unlink a directory (except for
  2298                              <1> 	; the superuser).
  2299                              <1> 	;
  2300                              <1> 	; Calling sequence:
  2301                              <1> 	;	sysunlink; name
  2302                              <1> 	; Arguments:
  2303                              <1> 	;	name - name of directory entry to be removed 
  2304                              <1> 	; Inputs: -
  2305                              <1> 	; Outputs: -
  2306                              <1> 	; ...............................................................
  2307                              <1> 	;				
  2308                              <1> 	; Retro UNIX 8086 v1 modification:
  2309                              <1> 	;	 The user/application program puts address of the name
  2310                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2311                              <1> 
  2312                              <1> 	; / name - remove link name
  2313 00004438 891D[646F0000]      <1> 	mov	[u.namep], ebx
  2314                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2315 0000443E E891050000          <1> 	call	namei
  2316                              <1> 		; jsr r0,namei / find the i-number associated 
  2317                              <1> 			     ; / with the path name
  2318                              <1> 	;jc	error
  2319                              <1> 		; br error9 / not found
  2320 00004443 730F                <1> 	jnc	short sysunlink1
  2321                              <1> 	; 'file not found !' error
  2322 00004445 C705[A16F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2322 0000444D 0000                <1>
  2323 0000444F E973F6FFFF          <1> 	jmp	error
  2324                              <1> sysunlink1:
  2325 00004454 50                  <1> 	push	eax ; 24/12/2021
  2326                              <1> 	;push	ax
  2327                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2328 00004455 E8A9FFFFFF          <1> 	call	isdir
  2329                              <1> 		; jsr r0,isdir / is it a directory
  2330                              <1> 	;xor 	ax, ax
  2331                              <1> 	; 24/12/2021
  2332 0000445A 31C0                <1> 	xor	eax, eax
  2333 0000445C 66A3[7E6F0000]      <1> 	mov	[u.dirbuf], ax ; 0
  2334                              <1> 		; clr u.dirbuf / no, clear the location that will
  2335                              <1> 			   ; / get written into the i-number portion
  2336                              <1> 			 ; / of the entry
  2337 00004462 832D[686F0000]10    <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2338                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2339 00004469 E868000000          <1> 	call	wdir
  2340                              <1> 		; jsr r0,wdir / free the directory entry
  2341 0000446E 58                  <1> 	pop	eax ; 24/12/2021
  2342                              <1> 	;pop	ax
  2343                              <1> 		; mov (sp)+,r1 / get i-number back
  2344 0000446F E8700D0000          <1> 	call	iget
  2345                              <1> 		; jsr r0,iget / get i-node
  2346 00004474 E8750E0000          <1> 	call	setimod
  2347                              <1> 		; jsr r0,setimod / set modified flag
  2348 00004479 FE0D[4A6C0000]      <1> 	dec	byte [i.nlks]
  2349                              <1> 		; decb i.nlks / decrement the number of links
  2350                              <1> 	; 24/12/2021
  2351 0000447F 7505                <1> 	jnz	short sysunlink_2
  2352                              <1> 	;jnz	sysret
  2353                              <1> 		; bgt sysret9 / if this was not the last link
  2354                              <1> 			    ; / to file return
  2355                              <1> 	; AX = r1 = i-number
  2356 00004481 E8B3090000          <1> 	call	anyi
  2357                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2358                              <1> 			 ; / Then free contents of file and destroy it.
  2359                              <1> sysunlink_2:
  2360 00004486 E95CF6FFFF          <1> 	jmp	sysret
  2361                              <1> 		; br sysret9
  2362                              <1> 
  2363                              <1> mkdir:
  2364                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2365                              <1> 	; 04/12/2015 (14 byte directory names)
  2366                              <1> 	; 12/10/2015
  2367                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2368                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2369                              <1> 	;
  2370                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2371                              <1> 	; by u.namep into the current directory.
  2372                              <1> 	;
  2373                              <1> 	; INPUTS ->
  2374                              <1> 	;    u.namep - points to a file name 
  2375                              <1> 	;	           that is about to be a directory entry.
  2376                              <1> 	;    ii - current directory's i-number.	
  2377                              <1> 	; OUTPUTS ->
  2378                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2379                              <1> 	;    u.off - points to entry to be filled 
  2380                              <1> 	;	     in the current directory		
  2381                              <1> 	;    u.base - points to start of u.dirbuf.
  2382                              <1> 	;    r1 - contains i-number of current directory 
  2383                              <1> 	;	
  2384                              <1> 	; ((AX = R1)) output
  2385                              <1> 	;
  2386                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2387                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2388                              <1> 	;
  2389                              <1> 
  2390                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2391 0000448B 31C0                <1> 	xor 	eax, eax
  2392 0000448D BF[806F0000]        <1> 	mov     edi, u.dirbuf+2
  2393 00004492 89FE                <1> 	mov	esi, edi
  2394 00004494 AB                  <1> 	stosd
  2395 00004495 AB                  <1> 	stosd
  2396                              <1> 	; 04/12/2015 (14 byte directory names)
  2397 00004496 AB                  <1> 	stosd
  2398 00004497 66AB                <1> 	stosw
  2399                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2400 00004499 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2401                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2402                              <1> 	;mov 	ebp, [u.namep]
  2403 0000449B E8B3060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2404                              <1> 		; esi = physical address (page start + offset)
  2405                              <1> 		; ecx = byte count in the page (1 - 4096)
  2406                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2407                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2408                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2409                              <1> mkdir_1: ; 1: 
  2410 000044A0 45                  <1> 	inc	ebp ; 12/10/2015
  2411                              <1> 	;
  2412                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2413                              <1> 	 ; 01/08/2013
  2414 000044A1 AC                  <1> 	lodsb
  2415                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2416 000044A2 20C0                <1> 	and 	al, al
  2417 000044A4 7426                <1> 	jz 	short mkdir_3 	  
  2418                              <1> 		; beq 1f / if null, done
  2419 000044A6 3C2F                <1> 	cmp	al, '/'
  2420                              <1> 		; cmp r1,$'/ / is it a "/"?
  2421 000044A8 7413                <1> 	je	short mkdir_err
  2422                              <1> 	;je	error
  2423                              <1> 		; beq error9 / yes, error
  2424                              <1> 	; 12/10/2015
  2425                              <1> 	;dec	cx
  2426 000044AA 49                  <1> 	dec	ecx ; 24/12/2021
  2427 000044AB 7505                <1> 	jnz	short mkdir_2
  2428                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2429 000044AD E8A7060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2430                              <1> 		; esi = physical address (page start + offset)
  2431                              <1> 		; ecx = byte count in the page
  2432                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2433                              <1> mkdir_2:
  2434 000044B2 81FF[8E6F0000]      <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2435                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2436                              <1> 				     ; / a char?
  2437 000044B8 74E6                <1> 	je	short mkdir_1
  2438                              <1> 		; beq 1b / yes, go back
  2439 000044BA AA                  <1> 	stosb
  2440                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2441 000044BB EBE3                <1> 	jmp 	short mkdir_1
  2442                              <1> 		; br 1b / get next char
  2443                              <1> mkdir_err:
  2444                              <1> 	; 17/06/2015
  2445 000044BD C705[A16F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2445 000044C5 0000                <1>
  2446 000044C7 E9FBF5FFFF          <1> 	jmp	error
  2447                              <1> 
  2448                              <1> mkdir_3: ; 1:
  2449 000044CC A1[606F0000]        <1> 	mov	eax, [u.dirp]
  2450 000044D1 A3[686F0000]        <1> 	mov	[u.off], eax
  2451                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2452                              <1> 				 ; / slot to u.off
  2453                              <1> wdir: 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2454                              <1> 	; 29/04/2013
  2455 000044D6 C705[6C6F0000]-     <1>         mov     dword [u.base], u.dirbuf
  2455 000044DC [7E6F0000]          <1>
  2456                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2457 000044E0 C705[706F0000]1000- <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2457 000044E8 0000                <1>
  2458                              <1> 		; mov $10.,u.count / u.count = 10
  2459 000044EA 66A1[2C6F0000]      <1> 	mov	ax, [ii] 
  2460                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2461 000044F0 B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2462 000044F2 E8C10D0000          <1> 	call 	access
  2463                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2464                              <1> 				 ; / for writing
  2465                              <1> 	; AX = i-number of current directory
  2466                              <1> 	; 01/08/2013
  2467 000044F7 FE05[B36F0000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2468                              <1> 	;call	writei
  2469                              <1> 	;	; jsr r0,writei / write into directory
  2470                              <1> 	;retn	
  2471                              <1> 	;	; rts r0
  2472                              <1> 	; 24/12/2021
  2473 000044FD E9A4100000          <1> 	jmp	writei
  2474                              <1> 
  2475                              <1> sysexec:
  2476                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2477                              <1> 	; 03/02/2022
  2478                              <1> 	; 12/01/2022
  2479                              <1> 	; 08/01/2022
  2480                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2481                              <1> 	; 23/10/2015
  2482                              <1> 	; 19/10/2015
  2483                              <1> 	; 10/10/2015, 18/10/2015
  2484                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2485                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2486                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2487                              <1> 	; 24/06/2015, 25/06/2015
  2488                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2489                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2490                              <1> 	;
  2491                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2492                              <1> 	; pointed to by 'name' in the sysexec call. 
  2493                              <1> 	; 'sysexec' performs the following operations:
  2494                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2495                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2496                              <1> 	;    3. sets trap vectors to system routines.
  2497                              <1> 	;    4. loads arguments to be passed to executing file into
  2498                              <1> 	;	highest locations of user's core
  2499                              <1> 	;    5. puts pointers to arguments in locations immediately
  2500                              <1> 	;	following arguments.
  2501                              <1> 	;    6.	saves number of arguments in next location.
  2502                              <1> 	;    7. initializes user's stack area so that all registers
  2503                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2504                              <1> 	;	to core when 'sysret' restores registers 
  2505                              <1> 	;	and does an rti.
  2506                              <1> 	;    8. inializes u.r0 and u.sp
  2507                              <1> 	;    9. zeros user's core down to u.r0
  2508                              <1> 	;   10.	reads executable file from storage device into core
  2509                              <1> 	;	starting at location 'core'.
  2510                              <1> 	;   11.	sets u.break to point to end of user's code with
  2511                              <1> 	;	data area appended.
  2512                              <1> 	;   12.	calls 'sysret' which returns control at location
  2513                              <1> 	;	'core' via 'rti' instruction. 		  		
  2514                              <1> 	;
  2515                              <1> 	; Calling sequence:
  2516                              <1> 	;	sysexec; namep; argp
  2517                              <1> 	; Arguments:
  2518                              <1> 	;	namep - points to pathname of file to be executed
  2519                              <1> 	;	argp  - address of table of argument pointers
  2520                              <1> 	;	argp1... argpn - table of argument pointers
  2521                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2522                              <1> 	; Inputs: (arguments)
  2523                              <1> 	; Outputs: -	
  2524                              <1> 	; ...............................................................
  2525                              <1> 	;
  2526                              <1> 	; Retro UNIX 386 v1 modification: 
  2527                              <1> 	;	User application runs in it's own virtual space 
  2528                              <1> 	;	which is izolated from kernel memory (and other
  2529                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2530                              <1> 	;	privilige mode. Virtual start address is always 0.
  2531                              <1> 	;	User's core memory starts at linear address 400000h
  2532                              <1> 	;	(the end of the 1st 4MB).
  2533                              <1> 	;
  2534                              <1> 	; Retro UNIX 8086 v1 modification: 
  2535                              <1> 	;	user/application segment and system/kernel segment
  2536                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2537                              <1> 	;	are different (user's registers are saved to 
  2538                              <1> 	;	and then restored from system's stack.)
  2539                              <1> 	;
  2540                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2541                              <1> 	;	      arguments which were in these registers;
  2542                              <1> 	;	      but, it returns by putting the 1st argument
  2543                              <1> 	;	      in 'u.namep' and the 2nd argument
  2544                              <1> 	;	      on top of stack. (1st argument is offset of the
  2545                              <1> 	;	      file/path name in the user's program segment.)		 	
  2546                              <1> 	
  2547                              <1> 	;call	arg2
  2548                              <1> 	; * name - 'u.namep' points to address of file/path name
  2549                              <1> 	;          in the user's program segment ('u.segmnt')
  2550                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2551                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2552                              <1> 	;          which is on top of stack.
  2553                              <1> 	;
  2554                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2555                              <1> 
  2556                              <1> 	; 23/06/2015 (32 bit modifications)
  2557                              <1> 
  2558 00004502 891D[646F0000]      <1> 	mov	[u.namep], ebx ; argument 1
  2559                              <1>         ; 18/10/2015
  2560 00004508 890D[CC6F0000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2561 0000450E E8C1040000          <1> 	call	namei
  2562                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2563                              <1> 			     ; / named in sysexec call in r1
  2564                              <1> 	;jc	error
  2565                              <1> 		; br error9
  2566 00004513 731E                <1> 	jnc	short sysexec_0
  2567                              <1> 	;
  2568                              <1> 	; 'file not found !' error
  2569 00004515 C705[A16F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2569 0000451D 0000                <1>
  2570 0000451F E9A3F5FFFF          <1> 	jmp	error 
  2571                              <1> sysexec_not_exf:
  2572                              <1> 	; 'not executable file !' error
  2573 00004524 C705[A16F0000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2573 0000452C 0000                <1>
  2574 0000452E E994F5FFFF          <1> 	jmp	error 
  2575                              <1> sysexec_0:
  2576 00004533 E8AC0C0000          <1> 	call	iget
  2577                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2578                              <1> 	; 24/12/2021
  2579 00004538 F605[486C0000]10    <1> 	test	byte [i.flgs], 10h
  2580                              <1> 	;test	word [i.flgs], 10h
  2581                              <1> 	;	; bit $20,i.flgs / is file executable
  2582 0000453F 74E3                <1> 	jz	short sysexec_not_exf
  2583                              <1> 	;jz	error
  2584                              <1> 		; beq error9
  2585                              <1> 	;;
  2586 00004541 E883140000          <1> 	call	iopen
  2587                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2588                              <1> 			     ; / given in r1 (opens file)
  2589                              <1> 	; AX = i-number of the file
  2590                              <1> 	; 24/12/2021
  2591 00004546 F605[486C0000]20    <1> 	test	byte [i.flgs], 20h
  2592                              <1> 	;test	word [i.flgs], 20h
  2593                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2594 0000454D 7415                <1> 	jz	short sysexec_1
  2595                              <1> 		; beq 1f
  2596 0000454F 803D[986F0000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2597                              <1> 		; tstb u.uid / test user id
  2598 00004556 760C                <1> 	jna	short sysexec_1
  2599                              <1> 		; beq 1f / super user
  2600 00004558 8A0D[4B6C0000]      <1> 	mov	cl, [i.uid]
  2601 0000455E 880D[986F0000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2602                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2603                              <1> 				 ; / as process user id
  2604                              <1> sysexec_1:
  2605                              <1> 	; 03/02/2022
  2606                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2607                              <1> 	; 18/10/2215
  2608                              <1> 	; 10/10/2015
  2609                              <1> 	; 21/07/2015, 24/07/2015
  2610                              <1> 	; 24/06/2015, 25/06/2015
  2611                              <1>         ; Moving arguments to the end of [u.upage]
  2612                              <1> 	; (by regarding page borders in user's memory space)
  2613                              <1> 	;
  2614                              <1> 	; 10/10/2015
  2615                              <1> 	; 21/07/2015
  2616 00004564 89E5                <1> 	mov	ebp, esp ; (**)
  2617                              <1> 	; 18/10/2015
  2618 00004566 89EF                <1> 	mov 	edi, ebp
  2619 00004568 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2620                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2621 0000456D 29CF                <1> 	sub	edi, ecx
  2622 0000456F 89FC                <1> 	mov	esp, edi
  2623 00004571 31C0                <1> 	xor	eax, eax
  2624 00004573 A3[746F0000]        <1> 	mov 	[u.nread], eax ; 0
  2625                              <1> 	; 12/01/2022
  2626                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2627                              <1> 	; may leave it with any value after an error))
  2628                              <1> 	;mov	[argc], ax
  2629 00004578 A2[CA6F0000]        <1> 	mov	[argc], al ; 0
  2630                              <1> 	;
  2631 0000457D 49                  <1> 	dec	ecx ; 256 - 1
  2632 0000457E 890D[706F0000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2633                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2634                              <1> sysexec_2:
  2635 00004584 8B35[CC6F0000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2636 0000458A E863020000          <1> 	call	get_argp
  2637                              <1> 	;mov	ecx, 4 
  2638                              <1> 	; 03/02/2022
  2639 0000458F 31C9                <1> 	xor	ecx, ecx
  2640 00004591 B104                <1> 	mov	cl, 4
  2641                              <1> sysexec_3:
  2642 00004593 21C0                <1> 	and	eax, eax
  2643 00004595 7455                <1> 	jz	short sysexec_6
  2644                              <1> 	; 18/10/2015
  2645 00004597 010D[CC6F0000]      <1> 	add	[argv], ecx ; 4
  2646                              <1> 	;inc	word [argc]
  2647                              <1> 	; 12/01/2022 ; ([argc] < 32)
  2648 0000459D FE05[CA6F0000]      <1> 	inc	byte [argc]
  2649                              <1> 	;
  2650 000045A3 A3[6C6F0000]        <1> 	mov	[u.base], eax
  2651                              <1>  	; 23/10/2015
  2652 000045A8 66C705[B16F0000]00- <1> 	mov	word [u.pcount], 0
  2652 000045B0 00                  <1>
  2653                              <1> sysexec_4:
  2654 000045B1 E8A5110000          <1> 	call	cpass ; get a character from user's core memory
  2655 000045B6 750B                <1>         jnz	short sysexec_5
  2656                              <1> 		; (max. 255 chars + null)
  2657                              <1> 	; 18/10/2015
  2658 000045B8 28C0                <1> 	sub 	al, al
  2659 000045BA AA                  <1> 	stosb
  2660 000045BB FF05[746F0000]      <1> 	inc	dword [u.nread]
  2661 000045C1 EB29                <1> 	jmp	short sysexec_6
  2662                              <1> sysexec_5:
  2663 000045C3 AA                  <1> 	stosb
  2664 000045C4 20C0                <1> 	and 	al, al
  2665 000045C6 75E9                <1> 	jnz	short sysexec_4
  2666                              <1> 	;mov	ecx, 4
  2667                              <1> 	; 24/12/2021
  2668 000045C8 29C9                <1> 	sub	ecx, ecx
  2669 000045CA B104                <1> 	mov	cl, 4
  2670                              <1> 	;cmp	[ncount], ecx ; 4
  2671                              <1> 	; 24/12/2021
  2672 000045CC 66390D[C86F0000]    <1> 	cmp	[ncount], cx ; 4
  2673 000045D3 72AF                <1> 	jb	short sysexec_2
  2674 000045D5 8B35[C46F0000]      <1> 	mov	esi, [nbase]
  2675 000045DB 010D[C46F0000]      <1> 	add	[nbase], ecx ; 4	
  2676 000045E1 66290D[C86F0000]    <1> 	sub	[ncount], cx 
  2677 000045E8 8B06                <1> 	mov	eax, [esi]
  2678 000045EA EBA7                <1> 	jmp	short sysexec_3
  2679                              <1> sysexec_6:
  2680                              <1> 	; 18/10/2015
  2681                              <1> 	; argument list transfer from user's core memory to
  2682                              <1> 	; kernel stack frame is OK here.
  2683                              <1> 	; [u.nread] = ; argument list length
  2684                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2685                              <1> 	;
  2686                              <1> 	; 18/10/2015
  2687                              <1> 	; 24/07/2015
  2688                              <1>         ; 21/07/2015
  2689                              <1> 	; 02/07/2015
  2690                              <1> 	; 25/06/2015
  2691                              <1> 	; 24/06/2015
  2692                              <1> 	; 23/06/2015
  2693                              <1> 	;
  2694 000045EC 8B1D[A96F0000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2695 000045F2 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2696 000045F4 740A                <1> 	jz	short sysexec_7
  2697 000045F6 A1[A56F0000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2698 000045FB E8E6E8FFFF          <1> 	call	deallocate_page_dir
  2699                              <1> sysexec_7:
  2700 00004600 E816E8FFFF          <1> 	call	make_page_dir
  2701                              <1> 	;jc	short sysexec_14
  2702                              <1> 	;jc	panic  ; allocation error 
  2703                              <1> 		       ; after a deallocation would be nonsence !?
  2704                              <1> 	; 08/01/2022
  2705 00004605 7243                <1> 	jc	short sysexec_panic
  2706                              <1> 
  2707                              <1> 	; 24/07/2015
  2708                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2709                              <1> 	;     of the user's page directory
  2710                              <1> 	;     (It is needed for interrupts!)
  2711                              <1> 	; 18/10/2015
  2712 00004607 8B15[886B0000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2713 0000460D 8B02                <1> 	mov	eax, [edx] ; physical address of
  2714                              <1> 			   ; kernel's first page table (1st 4 MB)
  2715                              <1> 			   ; (PDE 0 of kernel's page directory)
  2716 0000460F 8B15[A56F0000]      <1> 	mov 	edx, [u.pgdir]
  2717 00004615 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2718                              <1> 	;
  2719                              <1> 	; 20/07/2015
  2720 00004617 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2721                              <1> 	; 18/10/2015
  2722 0000461C BE[BC6F0000]        <1> 	mov	esi, pcore ; physical start address
  2723                              <1> sysexec_8:	
  2724 00004621 B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2725 00004626 E80EE8FFFF          <1> 	call	make_page_table
  2726                              <1> 	;jc	panic
  2727                              <1> 	; 24/12/2021
  2728 0000462B 721D                <1> 	jc	short sysexec_panic
  2729                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2730 0000462D E815E8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2731                              <1> 	;jc	panic
  2732                              <1> 	; 24/12/2021
  2733 00004632 7216                <1> 	jc	short sysexec_panic
  2734                              <1> 	;
  2735 00004634 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2736                              <1> 	; ebx = virtual address (24/07/2015)
  2737                              <1> 	; 24/12/2021
  2738                              <1> 	;call 	add_to_swap_queue
  2739                              <1> 	; 18/10/2015
  2740 00004636 81FE[C06F0000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2741 0000463C 7411                <1> 	je	short sysexec_9 ; yes
  2742 0000463E BE[C06F0000]        <1> 	mov	esi, ecore  ; physical address of the last page 
  2743                              <1> 	; 20/07/2015
  2744 00004643 BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2745                              <1> 	; ebx = virtual end address + segment base address - 4K
  2746 00004648 EBD7                <1>         jmp     short sysexec_8
  2747                              <1> 
  2748                              <1> sysexec_panic:
  2749                              <1> 	; 26/03/2021
  2750 0000464A E937EDFFFF          <1> 	jmp	panic
  2751                              <1> 
  2752                              <1> sysexec_9:
  2753                              <1> 	; 18/10/2015
  2754                              <1> 	; 26/08/2015
  2755                              <1> 	; 25/06/2015
  2756                              <1> 	; move arguments from kernel stack to [ecore]
  2757                              <1> 	; (argument list/line will be copied from kernel stack
  2758                              <1> 	; frame to the last (stack) page of user's core memory)
  2759                              <1> 	; 18/10/2015
  2760 0000464F 8B3D[C06F0000]      <1> 	mov	edi, [ecore]
  2761 00004655 81C700100000        <1> 	add	edi, PAGE_SIZE
  2762                              <1> 	;movzx	eax, word [argc]
  2763                              <1> 	; 12/01/2022
  2764 0000465B 31C0                <1> 	xor	eax, eax
  2765 0000465D A0[CA6F0000]        <1> 	mov	al, [argc]
  2766 00004662 08C0                <1> 	or	al, al
  2767                              <1> 	;or	eax, eax
  2768 00004664 7509                <1> 	jnz	short sysexec_10
  2769 00004666 89FB                <1> 	mov 	ebx, edi
  2770 00004668 83EB04              <1> 	sub	ebx, 4 
  2771 0000466B 8903                <1> 	mov	[ebx], eax ; 0
  2772 0000466D EB43                <1> 	jmp 	short sysexec_13
  2773                              <1> sysexec_10:
  2774 0000466F 8B0D[746F0000]      <1> 	mov	ecx, [u.nread]
  2775                              <1> 	;mov 	esi, [argv]
  2776 00004675 89E6                <1> 	mov	esi, esp ; start address of argument list
  2777 00004677 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2778                              <1> 
  2779                              <1> 	;;;;
  2780                              <1> 	; 09/05/2022
  2781                              <1> 	; (move edi -backward- to dword boundary)
  2782                              <1> 	; ((this will prevent 'general protection fault' error
  2783                              <1> 	;  as result of a lodsd or dword move instruction
  2784                              <1> 	;  at the end of argument list))
  2785 00004679 83EF03              <1> 	sub	edi, 3
  2786 0000467C 83E7FC              <1> 	and	edi, ~3 ; (*)
  2787                              <1> 	;;;
  2788                              <1> 
  2789 0000467F 89C2                <1> 	mov	edx, eax
  2790                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2791 00004681 FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2792 00004683 C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2793                              <1> 	; edx <= 128
  2794 00004686 89FB                <1> 	mov	ebx, edi
  2795                              <1> 	; 09/05/2022 (*) - edi is already dword aligned -
  2796                              <1> 	;and	bl, 0FCh ; 32 bit (dword) alignment
  2797 00004688 29D3                <1> 	sub 	ebx, edx
  2798 0000468A 89FA                <1> 	mov	edx, edi
  2799 0000468C F3A4                <1> 	rep	movsb
  2800 0000468E 89D6                <1> 	mov 	esi, edx
  2801 00004690 89DF                <1> 	mov 	edi, ebx
  2802 00004692 BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2803 00004697 2B15[C06F0000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2804 0000469D AB                  <1> 	stosd	; eax = argument count	
  2805                              <1> sysexec_11:
  2806 0000469E 89F0                <1> 	mov	eax, esi
  2807 000046A0 01D0                <1> 	add	eax, edx
  2808 000046A2 AB                  <1> 	stosd  ; eax = virtual address
  2809 000046A3 FE0D[CA6F0000]      <1> 	dec	byte [argc]
  2810 000046A9 7407                <1> 	jz	short sysexec_13
  2811                              <1> sysexec_12:
  2812 000046AB AC                  <1> 	lodsb
  2813 000046AC 20C0                <1> 	and	al, al
  2814 000046AE 75FB                <1> 	jnz	short sysexec_12
  2815 000046B0 EBEC                <1> 	jmp	short sysexec_11
  2816                              <1> 	;
  2817                              <1> 	; 1:
  2818                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2819                              <1> 			     ; / pointers to arguments to be passed
  2820                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2821                              <1> 			      ; / u.quit = 1 take quit
  2822                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2823                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2824                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2825                              <1> 			       ; / system routine
  2826                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2827                              <1> 			       ; / set to take system routine
  2828                              <1> 		; mov $sstack,sp / stack space used during swapping
  2829                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2830                              <1> 		; mov $ecore,r5 / r5 has end of core
  2831                              <1> 		; mov $core,r4 / r4 has start of users core
  2832                              <1> 		; mov r4,u.base / u.base has start of users core
  2833                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2834                              <1> 	; 1:
  2835                              <1> 		; tst (r2)+ / argument char = "nul"
  2836                              <1> 		; bne 1b
  2837                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2838                              <1> 			  ; / end of argument pointer list
  2839                              <1> 	; 1:
  2840                              <1> 	     ; / move arguments to bottom of users core
  2841                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2842                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2843                              <1> 			    ; / ptr list
  2844                              <1> 		; blo 1f / branch to 1f when all arguments
  2845                              <1> 		       ; / are moved
  2846                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2847                              <1> 	; 2:
  2848                              <1> 		; tstb (r3)+
  2849                              <1> 		; bne 2b / scan argument for \0 (nul)
  2850                              <1> 
  2851                              <1> 	; 2:
  2852                              <1> 		; movb -(r3),-(r5) / move argument char 
  2853                              <1> 				 ; / by char starting at "ecore"
  2854                              <1> 		; cmp r3,(r2) / moved all characters in 
  2855                              <1> 			    ; / this argument
  2856                              <1> 		; bhi 2b / branch 2b if not
  2857                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2858                              <1> 			     ; / r5 has pointer to nth arg
  2859                              <1> 		; br 1b / string
  2860                              <1> 	; 1:
  2861                              <1> 		; clrb -(r5)
  2862                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2863                              <1> 			; / last word of argument strings
  2864                              <1> 		; mov $core,r2
  2865                              <1> 	
  2866                              <1> 	; 1: / move argument pointers into core following 
  2867                              <1> 	      ; / argument strings
  2868                              <1> 		; cmp r2,r4
  2869                              <1> 		; bhis 1f / branch to 1f when all pointers
  2870                              <1> 			; / are moved
  2871                              <1> 		; mov (r2)+,-(r5)
  2872                              <1> 		; br 1b
  2873                              <1> 	; 1:
  2874                              <1> 		; sub $core,r4 / gives number of arguments *2
  2875                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2876                              <1> 		       ; / the number of args stored
  2877                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2878                              <1> 			     ; / of the argument pointers
  2879                              <1> sysexec_13:
  2880                              <1> 	; 19/10/2015
  2881                              <1> 	; 18/10/2015
  2882                              <1> 	; 29/07/2015
  2883                              <1> 	; 25/07/2015
  2884                              <1> 	; 24/07/2015
  2885                              <1> 	; 20/07/2015
  2886                              <1> 	; 25/06/2015
  2887                              <1> 	; 24/06/2015
  2888                              <1> 	; 23/06/2015
  2889                              <1> 	;
  2890                              <1> 	; moving arguments to [ecore] is OK here..
  2891                              <1> 	; 18/10/2015
  2892 000046B2 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2893                              <1> 	; ebx = beginning addres of argument list pointers
  2894                              <1> 	;	in user's stack
  2895                              <1> 	; 19/10/2015
  2896 000046B4 2B1D[C06F0000]      <1> 	sub 	ebx, [ecore]
  2897 000046BA 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2898                              <1> 			; end of core - 4096 (last page)
  2899                              <1> 			; (virtual address)
  2900 000046C0 891D[CC6F0000]      <1> 	mov	[argv], ebx
  2901 000046C6 891D[786F0000]      <1> 	mov	[u.break], ebx ; available user memory
  2902                              <1> 	;
  2903 000046CC 29C0                <1> 	sub	eax, eax
  2904 000046CE C705[706F0000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2904 000046D6 0000                <1>
  2905                              <1> 		; mov $14,u.count
  2906 000046D8 C705[5C6F0000]-     <1> 	mov	dword [u.fofp], u.off
  2906 000046DE [686F0000]          <1>
  2907                              <1> 		; mov $u.off,u.fofp
  2908 000046E2 A3[686F0000]        <1> 	mov	[u.off], eax ; 0
  2909                              <1> 		; clr u.off / set offset in file to be read to zero
  2910                              <1> 	; 25/07/2015
  2911 000046E7 A3[6C6F0000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2912                              <1> 	; 25/06/2015 
  2913 000046EC 66A1[2C6F0000]      <1> 	mov	ax, [ii]
  2914                              <1> 	; AX = i-number of the executable file
  2915 000046F2 E8C10C0000          <1> 	call	readi
  2916                              <1> 		; jsr r0,readi / read in first six words of 
  2917                              <1> 			; / user's file, starting at $core
  2918                              <1> 		; mov sp,r5 / put users stack address in r5
  2919                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2920                              <1> 				; / from r5 (leaves number of words
  2921                              <1> 				; / less 26 available for
  2922                              <1> 			     	; / program in user core
  2923                              <1> 		; mov r5,u.count /
  2924                              <1> 	; 25/06/2015
  2925 000046F7 8B0D[786F0000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2926 000046FD 890D[706F0000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2927                              <1> 	;
  2928 00004703 8B0D[746F0000]      <1> 	mov	ecx, [u.nread]
  2929 00004709 890D[786F0000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2930 0000470F 80F920              <1> 	cmp	cl, 32
  2931 00004712 7540                <1>         jne     short sysexec_15
  2932                              <1> 	;:
  2933                              <1> 	; 25/06/2015
  2934                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2935                              <1> 	; 18/10/2015
  2936 00004714 8B35[BC6F0000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2937                              <1> 		             ; (phys. start addr. of the exec. file)
  2938 0000471A AD                  <1> 	lodsd
  2939 0000471B 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBH, 1Eh -> jump to +32
  2940 0000471F 7533                <1> 	jne	short sysexec_15
  2941                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2942                              <1> 			      ; / if file is standard a.out format
  2943                              <1> 		; bne 1f / branch, if not standard format
  2944 00004721 AD                  <1> 	lodsd
  2945 00004722 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2946 00004724 AD                  <1> 	lodsd
  2947 00004725 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2948                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2949                              <1> 		              ; / number of bytes in program text	
  2950                              <1> 		; sub $14,r5 / subtract 12
  2951 00004727 89CB                <1> 	mov	ebx, ecx
  2952                              <1> 	;
  2953                              <1> 	; 25/06/2015
  2954                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2955                              <1> 	;	and SINGLIX operating systems (as code template).
  2956                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2957                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2958                              <1> 	;	Overrun is not possible for current version. 	
  2959                              <1> 	;
  2960 00004729 AD                  <1> 	lodsd	
  2961 0000472A 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2962 0000472C 3B1D[706F0000]      <1> 	cmp	ebx, [u.count]
  2963 00004732 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2964                              <1> 	;
  2965                              <1> 	; 24/07/2015
  2966                              <1> 	; add bss section size to [u.break]
  2967 00004734 0105[786F0000]      <1> 	add 	[u.break], eax
  2968                              <1> 	;
  2969 0000473A 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2970                              <1> 	;cmp	ecx, [u.count]
  2971                              <1> 	;jnb	short sysexec_16
  2972                              <1> 		; cmp r5,u.count /
  2973                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2974 0000473D 890D[706F0000]      <1> 	mov	[u.count], ecx ; required read count
  2975                              <1> 		; mov r5,u.count
  2976                              <1> 	;
  2977 00004743 EB2A                <1> 	jmp	short sysexec_16
  2978                              <1> 	;
  2979                              <1> sysexec_14:
  2980                              <1> 	; 23/06/2015
  2981                              <1> 	; insufficient (out of) memory
  2982 00004745 C705[A16F0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2982 0000474D 0000                <1>
  2983 0000474F E973F3FFFF          <1> 	jmp	error
  2984                              <1> 	;
  2985                              <1> sysexec_15:
  2986                              <1> 	; 25/06/2015
  2987 00004754 0FB715[4C6C0000]    <1>         movzx   edx, word [i.size] ; file size
  2988 0000475B 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2989 0000475D 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2990 0000475F 01D1                <1> 	add	ecx, edx ; [i.size]
  2991 00004761 3B0D[706F0000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2992 00004767 77DC                <1> 	ja	short sysexec_14
  2993 00004769 8915[706F0000]      <1> 	mov	[u.count], edx
  2994                              <1> sysexec_16:
  2995 0000476F 66A1[2C6F0000]      <1> 	mov	ax, [ii] ; i-number
  2996 00004775 E83E0C0000          <1> 	call	readi
  2997                              <1> 		; add core+10,u.nread / add size of user data area 
  2998                              <1> 		                    ; / to u.nread
  2999                              <1> 		; br 2f
  3000                              <1> 	; 1:
  3001                              <1> 		; jsr r0,readi / read in rest of file
  3002                              <1> 	; 2:
  3003 0000477A 8B0D[746F0000]      <1> 	mov	ecx, [u.nread]
  3004 00004780 010D[786F0000]      <1> 	add	[u.break], ecx
  3005                              <1> 		; mov u.nread,u.break / set users program break to end of 
  3006                              <1> 				    ; / user code
  3007                              <1> 		; add $core+14,u.break / plus data area
  3008                              <1> sysexec_17: ; 20/07/2015
  3009                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3010                              <1> 	; ('iclose' is not needed for regular files, from now on)
  3011                              <1> 	;;mov	ax, [ii] ; i-number
  3012                              <1> 	;call	iclose
  3013                              <1> 	;	; jsr r0,iclose / does nothing
  3014 00004786 31C0                <1>         xor     eax, eax
  3015 00004788 FEC0                <1> 	inc	al
  3016 0000478A 66A3[906F0000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  3017 00004790 66A3[926F0000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  3018                              <1> 	; 02/07/2015
  3019 00004796 833D[A96F0000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  3020 0000479D 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  3021                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  3022 0000479F 8B15[886B0000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  3023 000047A5 8915[A96F0000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  3024                              <1> sysexec_18:
  3025                              <1> 	; 18/10/2015
  3026                              <1> 	; 05/08/2015
  3027                              <1> 	; 29/07/2015
  3028 000047AB 8B2D[CC6F0000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  3029                              <1> 			    ; list pointers (argument count)
  3030 000047B1 FA                  <1> 	cli
  3031 000047B2 8B25[246B0000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  3032                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  3033                              <1> 			    ; for this process	 
  3034                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  3035                              <1> 	;xor	eax, eax ; 0
  3036 000047B8 FEC8                <1> 	dec	al ; eax = 0
  3037 000047BA 66BA2300            <1> 	mov	dx, UDATA
  3038 000047BE 6652                <1> 	push	dx  ; user's stack segment
  3039 000047C0 55                  <1> 	push	ebp ; user's stack pointer
  3040                              <1> 		    ; (points to number of arguments)
  3041 000047C1 FB                  <1> 	sti
  3042 000047C2 9C                  <1> 	pushfd	; EFLAGS
  3043                              <1> 		; Set IF for enabling interrupts in user mode	
  3044                              <1> 	;or	dword [esp], 200h 
  3045                              <1> 	;
  3046                              <1> 	;mov	bx, UCODE
  3047                              <1> 	;push	bx ; user's code segment
  3048 000047C3 6A1B                <1> 	push	UCODE
  3049                              <1> 	;push	0
  3050 000047C5 50                  <1> 	push	eax ; EIP (=0) - start address -	
  3051                              <1> 		; clr -(r5) / popped into ps when rti in 
  3052                              <1> 			  ; / sysrele is executed
  3053                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  3054                              <1> 		                ; / in sysrele is executed
  3055                              <1> 		;mov r5,0f / load second copyz argument
  3056                              <1> 		;tst -(r5) / decrement r5
  3057 000047C6 8925[446F0000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  3058                              <1> 	; 05/08/2015
  3059                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  3060                              <1> 	; ('push dx' would cause to general protection fault, 
  3061                              <1> 	; after 'pop ds' etc.)
  3062                              <1> 	;
  3063                              <1> 	;; push dx ; ds (UDATA)
  3064                              <1> 	;; push dx ; es (UDATA)
  3065                              <1> 	;; push dx ; fs (UDATA)
  3066                              <1> 	;; push dx ; gs (UDATA)
  3067                              <1> 	;
  3068                              <1> 	; This is a trick to prevent general protection fault
  3069                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3070 000047CC 8EC2                <1> 	mov 	es, dx ; UDATA
  3071 000047CE 06                  <1> 	push 	es ; ds (UDATA)
  3072 000047CF 06                  <1> 	push 	es ; es (UDATA)
  3073 000047D0 06                  <1> 	push 	es ; fs (UDATA)
  3074 000047D1 06                  <1> 	push	es ; gs (UDATA)
  3075 000047D2 66BA1000            <1> 	mov	dx, KDATA
  3076 000047D6 8EC2                <1> 	mov	es, dx
  3077                              <1> 	;
  3078                              <1> 	;; pushad simulation
  3079 000047D8 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3080 000047DA 50                  <1> 	push	eax ; eax (0)
  3081 000047DB 50                  <1> 	push	eax ; ecx (0)
  3082 000047DC 50                  <1> 	push	eax ; edx (0)
  3083 000047DD 50                  <1> 	push	eax ; ebx (0)
  3084 000047DE 55                  <1> 	push	ebp ; esp before pushad
  3085 000047DF 50                  <1> 	push	eax ; ebp (0)
  3086 000047E0 50                  <1> 	push	eax ; esi (0)		
  3087 000047E1 50                  <1> 	push	eax ; edi (0)	
  3088                              <1> 	;
  3089 000047E2 A3[4C6F0000]        <1> 	mov	[u.r0], eax ; eax = 0
  3090 000047E7 8925[486F0000]      <1> 	mov	[u.usp], esp
  3091                              <1> 		; mov r5,u.r0 /
  3092                              <1> 		; sub $16.,r5 / skip 8 words
  3093                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3094                              <1> 		;             / effectively zeroes all regs
  3095                              <1> 			    ; / when sysrele is executed
  3096                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3097                              <1> 		; clr u.break
  3098                              <1> 		; mov r5,sp / point sp to user's stack
  3099                              <1> 	;
  3100 000047ED E9F7F2FFFF          <1> 	jmp	sysret0
  3101                              <1> 	;jmp	sysret
  3102                              <1> 		; br sysret3 / return to core image at $core
  3103                              <1> 
  3104                              <1> get_argp:
  3105                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3106                              <1> 	; 18/10/2015 (nbase, ncount)
  3107                              <1> 	; 21/07/2015
  3108                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3109                              <1> 	; Get (virtual) address of argument from user's core memory
  3110                              <1> 	;
  3111                              <1> 	; INPUT:
  3112                              <1> 	;	esi = virtual address of argument pointer
  3113                              <1> 	; OUTPUT:
  3114                              <1> 	;	eax = virtual address of argument
  3115                              <1> 	;
  3116                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3117                              <1> 	;
  3118 000047F2 833D[A96F0000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3119                              <1> 				    ; (the caller is kernel)
  3120                              <1> 	;jna	short get_argpk 
  3121                              <1> 	; 24/12/2021
  3122 000047F9 7719                <1> 	ja	short get_argp5
  3123                              <1> get_argpk:
  3124                              <1> 	; Argument is in kernel's memory space
  3125 000047FB 66C705[C86F0000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3125 00004803 10                  <1>
  3126 00004804 8935[C46F0000]      <1> 	mov	[nbase], esi
  3127 0000480A 8305[C46F0000]04    <1> 	add	dword [nbase], 4
  3128 00004811 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3129 00004813 C3                  <1> 	retn
  3130                              <1> get_argp5:
  3131 00004814 89F3                <1>      	mov	ebx, esi
  3132 00004816 E887E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3133 0000481B 7257                <1>         jc      short get_argp_err ; 24/12/2021 (short jump)
  3134 0000481D A3[C46F0000]        <1> 	mov 	[nbase], eax ; physical address	
  3135 00004822 66890D[C86F0000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3136 00004829 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3137                              <1> 	;cmp	cx, ax ; 4
  3138 0000482E 39C1                <1> 	cmp	ecx, eax ; 24/12/2021
  3139 00004830 734C                <1> 	jnb	short get_argp2
  3140 00004832 89F3                <1> 	mov	ebx, esi
  3141 00004834 01CB                <1> 	add	ebx, ecx
  3142 00004836 E867E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3143 0000483B 7237                <1> 	jc	short get_argp_err
  3144                              <1> 	;push	esi
  3145 0000483D 89C6                <1> 	mov	esi, eax
  3146 0000483F 66870D[C86F0000]    <1> 	xchg	cx, [ncount]
  3147 00004846 8735[C46F0000]      <1> 	xchg	esi, [nbase]
  3148 0000484C B504                <1> 	mov	ch, 4
  3149 0000484E 28CD                <1> 	sub	ch, cl
  3150                              <1> get_argp0:
  3151 00004850 AC                  <1> 	lodsb
  3152                              <1> 	;push	ax
  3153                              <1> 	; 24/12/2021
  3154 00004851 50                  <1> 	push	eax
  3155 00004852 FEC9                <1> 	dec	cl
  3156 00004854 75FA                <1>         jnz     short get_argp0
  3157 00004856 8B35[C46F0000]      <1> 	mov	esi, [nbase]
  3158                              <1> 	; 21/07/2015
  3159 0000485C 0FB6C5              <1> 	movzx	eax, ch
  3160 0000485F 0105[C46F0000]      <1> 	add	[nbase], eax
  3161 00004865 662905[C86F0000]    <1> 	sub	[ncount], ax
  3162                              <1> get_argp1:
  3163 0000486C AC                  <1> 	lodsb
  3164 0000486D FECD                <1> 	dec	ch
  3165 0000486F 7423                <1>         jz      short get_argp3
  3166                              <1> 	;push	ax
  3167                              <1> 	; 24/12/2021
  3168 00004871 50                  <1> 	push	eax
  3169 00004872 EBF8                <1> 	jmp     short get_argp1
  3170                              <1> 	; 24/12/2021
  3171                              <1> get_argp_err:
  3172 00004874 A3[A16F0000]        <1> 	mov	[u.error], eax
  3173 00004879 E949F2FFFF          <1> 	jmp	error
  3174                              <1> get_argp2:
  3175                              <1> 	; 21/07/2015
  3176                              <1> 	;mov	eax, 4
  3177 0000487E 8B15[C46F0000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3178 00004884 0105[C46F0000]      <1> 	add	[nbase], eax
  3179 0000488A 662905[C86F0000]    <1> 	sub	[ncount], ax
  3180                              <1> 	;
  3181 00004891 8B02                <1> 	mov	eax, [edx]
  3182 00004893 C3                  <1> 	retn
  3183                              <1> get_argp3:
  3184 00004894 B103                <1> 	mov	cl, 3
  3185                              <1> get_argp4:
  3186 00004896 C1E008              <1> 	shl	eax, 8
  3187                              <1> 	;pop	dx
  3188                              <1> 	; 24/12/2021
  3189 00004899 5A                  <1> 	pop	edx
  3190 0000489A 88D0                <1> 	mov 	al, dl
  3191 0000489C E2F8                <1>         loop    get_argp4
  3192                              <1> 	;pop	esi
  3193 0000489E C3                  <1> 	retn	
  3194                              <1> 
  3195                              <1> sysfstat:
  3196                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  3197                              <1> 	;	([idev] return in eax)
  3198                              <1> 	;	0 = root device
  3199                              <1> 	;	1 = mounted device (>0)
  3200                              <1> 	; 03/02/2022
  3201                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3202                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3203                              <1> 	;
  3204                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3205                              <1> 	; on open files instead of files given by name. It puts the
  3206                              <1> 	; buffer address on the stack, gets the i-number and
  3207                              <1> 	; checks to see if the file is open for reading or writing.
  3208                              <1> 	; If the file is open for writing (i-number is negative)
  3209                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3210                              <1> 	; is made.	
  3211                              <1> 	;
  3212                              <1> 	; Calling sequence:
  3213                              <1> 	;	sysfstat; buf
  3214                              <1> 	; Arguments:
  3215                              <1> 	;	buf - buffer address
  3216                              <1> 	;
  3217                              <1> 	; Inputs: *u.r0 - file descriptor
  3218                              <1> 	; Outputs: buffer is loaded with file information
  3219                              <1> 	; ...............................................................
  3220                              <1> 	;				
  3221                              <1> 	; Retro UNIX 8086 v1 modification:
  3222                              <1> 	;       'sysfstat' system call has two arguments; so,
  3223                              <1> 	;	* 1st argument, file descriptor is in BX register
  3224                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3225                              <1> 
  3226                              <1> 	; / set status of open file
  3227                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3228 0000489F 51                  <1> 	push	ecx
  3229                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3230                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3231                              <1> 		; jsr r0,getf / get the files i-number
  3232                              <1> 	; BX = file descriptor (file number)
  3233 000048A0 E8FE000000          <1> 	call	getf1
  3234                              <1> 	; 03/02/2022
  3235 000048A5 21C0                <1> 	and	eax, eax
  3236                              <1> 	;and	ax, ax ; i-number of the file
  3237                              <1> 		; tst	r1 / is it 0?
  3238                              <1> 	;jz	error
  3239                              <1> 		; beq error3 / yes, error
  3240 000048A7 750F                <1> 	jnz	short sysfstat1
  3241 000048A9 C705[A16F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3241 000048B1 0000                <1>
  3242 000048B3 E90FF2FFFF          <1> 	jmp	error
  3243                              <1> sysfstat1:
  3244 000048B8 80FC80              <1> 	cmp	ah, 80h
  3245 000048BB 7222                <1>         jb      short sysstat1
  3246                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3247 000048BD 66F7D8              <1> 	neg	ax
  3248                              <1> 		; neg r1 / make it positive, then branch
  3249 000048C0 EB1D                <1> 	jmp	short sysstat1
  3250                              <1> 		; br 1f / to 1f
  3251                              <1> sysstat:
  3252                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  3253                              <1> 	;	([idev] return in eax)
  3254                              <1> 	;	0 = root device
  3255                              <1> 	;	1 = mounted device (>0)
  3256                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3257                              <1> 	; 18/10/2015
  3258                              <1> 	; 07/10/2015
  3259                              <1> 	; 02/09/2015
  3260                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3261                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3262                              <1> 	;
  3263                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3264                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3265                              <1> 	; long and information about the file placed in it.	
  3266                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3267                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3268                              <1> 	; is then loaded and the results are given in the UNIX
  3269                              <1> 	; Programmers Manual sysstat (II).	
  3270                              <1> 	;
  3271                              <1> 	; Calling sequence:
  3272                              <1> 	;	sysstat; name; buf
  3273                              <1> 	; Arguments:
  3274                              <1> 	;	name - points to the name of the file
  3275                              <1> 	;	buf - address of a 34 bytes buffer
  3276                              <1> 	; Inputs: -
  3277                              <1> 	; Outputs: buffer is loaded with file information
  3278                              <1> 	; ...............................................................
  3279                              <1> 	;				
  3280                              <1> 	; Retro UNIX 8086 v1 modification: 
  3281                              <1> 	;       'sysstat' system call has two arguments; so,
  3282                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3283                              <1> 	;	to get sysstat system call arguments from the user;
  3284                              <1> 	;	* 1st argument, name is pointed to by BX register
  3285                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3286                              <1> 	;
  3287                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3288                              <1> 	;	      arguments which were in these registers;
  3289                              <1> 	;	      but, it returns by putting the 1st argument
  3290                              <1> 	;	      in 'u.namep' and the 2nd argument
  3291                              <1> 	;	      on top of stack. (1st argument is offset of the
  3292                              <1> 	;	      file/path name in the user's program segment.)		 	
  3293                              <1> 	
  3294                              <1> 	; / ; name of file; buffer - get files status
  3295                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3296 000048C2 891D[646F0000]      <1> 	mov	[u.namep], ebx
  3297 000048C8 51                  <1> 	push	ecx
  3298 000048C9 E806010000          <1> 	call	namei
  3299                              <1> 		; jsr r0,namei / get the i-number for the file
  3300                              <1> 	;jc	error
  3301                              <1> 		; br error3 / no such file, error
  3302 000048CE 730F                <1> 	jnc	short sysstat1
  3303                              <1> 	; pop 	ecx
  3304                              <1> sysstat_err0:
  3305                              <1> 	; 'file not found !' error
  3306 000048D0 C705[A16F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3306 000048D8 0000                <1>
  3307 000048DA E9E8F1FFFF          <1> 	jmp	error
  3308                              <1> 
  3309                              <1> ;statx: db 0
  3310                              <1> 
  3311                              <1> sysstat1: ; 1:
  3312 000048DF E800090000          <1> 	call	iget
  3313                              <1> 		; jsr r0,iget / get the i-node into core
  3314                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3315                              <1> 	; 02/09/2015
  3316 000048E4 8F05[6C6F0000]      <1> 	pop	dword [u.base]
  3317                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3318 000048EA E861000000          <1> 	call	sysstat_gpa ; get physical address
  3319 000048EF 730A                <1> 	jnc 	short sysstat2
  3320                              <1> sysstat_err1:
  3321 000048F1 A3[A16F0000]        <1> 	mov	dword [u.error], eax ; error code
  3322 000048F6 E9CCF1FFFF          <1> 	jmp	error
  3323                              <1> sysstat2:
  3324 000048FB A0[2C6F0000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3325 00004900 AA                  <1> 	stosb
  3326 00004901 FF05[6C6F0000]      <1> 	inc 	dword [u.base]
  3327                              <1> 	;dec 	cx
  3328                              <1> 	; 24/12/2021
  3329 00004907 49                  <1> 	dec	ecx
  3330 00004908 7505                <1> 	jnz	short sysstat3
  3331 0000490A E841000000          <1> 	call	sysstat_gpa
  3332                              <1> 	;jc	short sysstat_err1
  3333                              <1> sysstat3:
  3334 0000490F A0[2D6F0000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3335 00004914 AA                  <1> 	stosb
  3336                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3337 00004915 FF05[6C6F0000]      <1> 	inc 	dword [u.base]
  3338                              <1> 	;;dec 	word [u.pcount]
  3339                              <1> 	;dec	cx
  3340 0000491B 49                  <1> 	dec	ecx ; 24/12/2021
  3341 0000491C 7505                <1> 	jnz	short sysstat4
  3342 0000491E E82D000000          <1> 	call	sysstat_gpa
  3343                              <1> 	;jc	short sysstat_err1	
  3344                              <1> sysstat4:
  3345 00004923 BE[486C0000]        <1> 	mov	esi, inode
  3346                              <1> 		; mov $inode,r2 / r2 points to i-node
  3347                              <1> sysstat5: ; 1:
  3348 00004928 A4                  <1> 	movsb
  3349                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3350 00004929 FF05[6C6F0000]      <1> 	inc 	dword [u.base]
  3351                              <1> 	;;dec 	word [u.pcount]
  3352                              <1> 	;dec 	cx
  3353                              <1> 	; 24/12/2021
  3354 0000492F 49                  <1> 	dec	ecx
  3355 00004930 7505                <1> 	jnz	short sysstat6
  3356 00004932 E819000000          <1> 	call	sysstat_gpa
  3357                              <1> 	;jc	short sysstat_err1
  3358                              <1> sysstat6:		
  3359 00004937 81FE[686C0000]      <1> 	cmp	esi, inode + 32
  3360                              <1> 		; cmp r2,$inode+32 / done?
  3361 0000493D 75E9                <1> 	jne	short sysstat5
  3362                              <1> 		; bne 1b / no, go back
  3363                              <1> 
  3364                              <1> 	;;;
  3365                              <1> 	; 09/05/2022
  3366                              <1> 	;*** additional feature *** -retro unix only- 
  3367                              <1> 	;
  3368                              <1> 	; !! return device number -of current inode- in eax !!
  3369                              <1> 	;
  3370                              <1> 	; (modification reason/purpose:
  3371                              <1> 	; to improve 'pwd' command's pathname output/result
  3372                              <1> 	; and to correct 'cp' command's 'can not copy file itself'
  3373                              <1> 	; error due to same inode numbers in root file system
  3374                              <1> 	; and mounted file system.)
  3375                              <1> 	;
  3376 0000493F 29C0                <1> 	sub	eax, eax
  3377 00004941 A0[2E6F0000]        <1> 	mov	al, [idev] ; [cdev]
  3378 00004946 A3[4C6F0000]        <1> 	mov	[u.r0], eax
  3379                              <1> 	;;;  
  3380                              <1> 
  3381 0000494B E997F1FFFF          <1> 	jmp	sysret
  3382                              <1> 		; br sysret3 / return through sysret
  3383                              <1> 	;
  3384                              <1> sysstat_gpa: ; get physical address of file status buffer
  3385                              <1> 	; 02/09/2015
  3386 00004950 8B1D[6C6F0000]      <1> 	mov 	ebx, [u.base]
  3387                              <1> 	; 07/10/2015
  3388 00004956 E847E8FFFF          <1> 	call	get_physical_addr ; get physical address
  3389                              <1> 	;jc	short sysstat_gpa1
  3390 0000495B 7294                <1> 	jc	short sysstat_err1
  3391                              <1> 	; 18/10/2015
  3392 0000495D 89C7                <1> 	mov	edi, eax ; physical address
  3393                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3394                              <1> ;sysstat_gpa1:
  3395 0000495F C3                  <1> 	retn
  3396                              <1> 
  3397                              <1> fclose:
  3398                              <1> 	; 08/01/2022
  3399                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3400                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3401                              <1> 	;            (32 bit offset pointer modification)
  3402                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3403                              <1> 	;
  3404                              <1> 	; Given the file descriptor (index to the u.fp list)
  3405                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3406                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3407                              <1> 	; u.fp list is cleared. If all the processes that opened
  3408                              <1> 	; that file close it, then fsp etry is freed and the file
  3409                              <1> 	; is closed. If not a return is taken. 
  3410                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3411                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3412                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3413                              <1> 	; a check is made to see if the file is special.	
  3414                              <1> 	;
  3415                              <1> 	; INPUTS ->
  3416                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3417                              <1> 	;    u.fp - list of entries in the fsp table
  3418                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3419                              <1> 	; OUTPUTS ->
  3420                              <1> 	;    r1 - contains the same file descriptor
  3421                              <1> 	;    r2 - contains i-number
  3422                              <1> 	;
  3423                              <1> 	; ((AX = R1))
  3424                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3425                              <1> 	;
  3426                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3427                              <1> 	;              if i-number of the file is 0. (error)  	
  3428                              <1> 
  3429                              <1> 	;movzx	edx, ax ; **
  3430                              <1> 	; 24/12/2021
  3431                              <1> 	;movzx	edx, al
  3432 00004960 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 24/12/2021
  3433 00004962 50                  <1> 	push	eax ; ***
  3434                              <1> 	;push	ax ; ***
  3435                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3436                              <1> 			     ; / the index to u.fp list)
  3437 00004963 E839000000          <1> 	call	getf
  3438                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3439                              <1> 			    ; / cdev has device =, u.fofp 
  3440                              <1> 			    ; / points to 3rd word of fsp entry
  3441 00004968 6683F801            <1> 	cmp	ax, 1 ; r1
  3442                              <1> 		; tst r1 / is i-number 0?
  3443 0000496C 7231                <1> 	jb	short fclose_2
  3444                              <1> 		; beq 1f / yes, i-node not active so return
  3445                              <1> 		; tst (r0)+ / no, jump over error return
  3446 0000496E 89D3                <1> 	mov	ebx, edx ; **
  3447                              <1> 	; 24/12/2021
  3448 00004970 89C2                <1> 	mov	edx, eax ; *
  3449                              <1> 	;mov 	dx, ax ; *
  3450                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3451                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3452                              <1> 			    ; / which is index to u.fp ; **
  3453 00004972 C683[526F0000]00    <1> 	mov	byte [ebx+u.fp], 0
  3454                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3455 00004979 8B1D[5C6F0000]      <1> 	mov	ebx, [u.fofp]
  3456                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3457                              <1> fclose_0:
  3458 0000497F FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3459                              <1> 		; decb 2(r1) / decrement the number of processes 
  3460                              <1> 			   ; / that have opened the file
  3461 00004982 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3462                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3463                              <1> 	;
  3464                              <1> 	; 24/12/2021
  3465 00004984 52                  <1> 	push	edx ; *
  3466                              <1> 	;push	dx ; *
  3467                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3468                              <1> 	;xor	ax, ax ; 0
  3469                              <1> 	; 24/12/2021
  3470 00004985 31C0                <1> 	xor	eax, eax
  3471 00004987 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3472                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3473 0000498B 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3474                              <1> 		; tstb	3(r1) / has this file been deleted
  3475 0000498E 20C0                <1> 	and	al, al
  3476 00004990 7407                <1> 	jz	short fclose_1
  3477                              <1> 		; beq 2f / no, branch
  3478                              <1> 	; 08/01/2022
  3479 00004992 89D0                <1> 	mov	eax, edx
  3480                              <1> 	;mov	ax, dx ; *
  3481                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3482                              <1> 	; AX = inode number
  3483 00004994 E8A0040000          <1> 	call	anyi
  3484                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3485                              <1> 			    ; / check if file appears in fsp again
  3486                              <1> fclose_1: ; 2:
  3487                              <1> 	; 24/12/2021
  3488 00004999 58                  <1> 	pop	eax ; * 
  3489                              <1> 	;pop	ax ; *
  3490                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3491 0000499A E869110000          <1> 	call	iclose ; close if it is special file 
  3492                              <1> 		; jsr r0,iclose / check to see if its a special file
  3493                              <1> fclose_2: ; 1:
  3494                              <1> 	; 24/12/2021
  3495 0000499F 58                  <1> 	pop	eax ; ***
  3496                              <1> 	;pop	ax ; ***
  3497                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3498 000049A0 C3                  <1> 	retn
  3499                              <1> 		; rts r0
  3500                              <1> 
  3501                              <1> 	; 09/01/2022
  3502                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1. - Kernel v0.2.1.2)
  3503                              <1> getf:	; / get the device number and the i-number of an open file
  3504                              <1> 	; 13/05/2015
  3505                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3506                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3507                              <1> 	;
  3508 000049A1 89C3                <1> 	mov	ebx, eax
  3509                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3510                              <1> 	; 08/01/2022
  3511 000049A3 29C0                <1> 	sub	eax, eax
  3512                              <1> 	;
  3513 000049A5 83FB0A              <1> 	cmp	ebx, 10
  3514                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3515 000049A8 7329                <1>         jnb	short getf2 ; 13/05/2015
  3516                              <1> 	;jnb	error
  3517                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3518                              <1> 			    ; / index in fsp table
  3519                              <1> 	; 08/01/2022
  3520 000049AA 8A83[526F0000]      <1> 	mov	al, [ebx+u.fp]
  3521                              <1> 	;mov	bl, [ebx+u.fp]
  3522                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3523                              <1> 		                  ; / in fsp table
  3524                              <1> 	; 08/01/2022
  3525 000049B0 08C0                <1> 	or	al, al
  3526 000049B2 741F                <1> 	jz	short getf2	
  3527                              <1> 	;or	bl, bl
  3528                              <1> 	;jnz	short getf3
  3529                              <1> 	;;jz	short getf4
  3530                              <1> 		; beq 1f / if its zero return
  3531                              <1> ;getf2:
  3532                              <1> ;	; 08/01/2022
  3533                              <1> ;	; 'File not open !' error (ax=0)
  3534                              <1> ;	;sub	eax, eax
  3535                              <1> ;	retn
  3536                              <1> 
  3537                              <1> getf3:	
  3538                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3539                              <1> 	;
  3540                              <1> 	; 'fsp' table (10 bytes/entry)
  3541                              <1> 	; bit 15				   bit 0
  3542                              <1> 	; ---|-------------------------------------------
  3543                              <1> 	; r/w|		i-number of open file
  3544                              <1> 	; ---|-------------------------------------------
  3545                              <1> 	;		   device number
  3546                              <1> 	; -----------------------------------------------
  3547                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3548                              <1> 	; -----------------------------------------------
  3549                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3550                              <1> 	; ----------------------|------------------------
  3551                              <1> 	;  flag that says file 	| number of processes
  3552                              <1> 	;   has been deleted	| that have file open 
  3553                              <1> 	; ----------------------|------------------------
  3554                              <1> 	;
  3555                              <1> 	;mov	eax, 10
  3556                              <1> 	; 08/01/2022
  3557 000049B4 B30A                <1> 	mov	bl, 10
  3558 000049B6 F6E3                <1> 	mul	bl
  3559 000049B8 BB[126D0000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3560 000049BD 01C3                <1> 	add	ebx, eax
  3561                              <1> 		; asl r1
  3562                              <1> 		; asl r1 / multiply by 8 to get index into 
  3563                              <1> 		       ; / fsp table entry
  3564                              <1> 		; asl r1
  3565                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3566                              <1> 			      ; / in the fsp entry
  3567 000049BF 891D[5C6F0000]      <1> 	mov	[u.fofp], ebx
  3568                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3569                              <1> 			      ; / in fsp entry in u.fofp
  3570 000049C5 4B                  <1> 	dec	ebx
  3571 000049C6 4B                  <1> 	dec	ebx
  3572                              <1> 	;mov	ax, [ebx]
  3573                              <1> 	; 09/01/2022
  3574 000049C7 8A03                <1> 	mov	al, [ebx]
  3575 000049C9 A2[2F6F0000]        <1> 	mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3576                              <1> 	;mov	[cdev], ax ; ;;in fact (!) 
  3577                              <1> 			     ;;dev number is in 1 byte
  3578                              <1> 		; mov -(r1),cdev / remove the device number cdev
  3579 000049CE 4B                  <1> 	dec	ebx
  3580 000049CF 4B                  <1> 	dec	ebx
  3581 000049D0 668B03              <1> 	mov	ax, [ebx]
  3582                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3583                              <1> getf2:	; 08/01/2022
  3584                              <1> getf4:	; 1:
  3585 000049D3 C3                  <1> 	retn
  3586                              <1> 		; rts r0
  3587                              <1> 
  3588                              <1> namei:
  3589                              <1> 	; 15/05/2022 (mounted directory path, '..' method)
  3590                              <1> 	; 03/02/2022
  3591                              <1> 	; 09/01/2022
  3592                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3593                              <1> 	; 04/12/2015 (Retro UNIX 386 v1.1, 14 byte file names)
  3594                              <1> 	; 18/10/2015 (nbase, ncount)
  3595                              <1> 	; 12/10/2015
  3596                              <1> 	; 21/08/2015
  3597                              <1> 	; 18/07/2015
  3598                              <1> 	; 02/07/2015
  3599                              <1> 	; 17/06/2015
  3600                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3601                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3602                              <1> 	;
  3603                              <1> 	; 'namei' takes a file path name and returns i-number of
  3604                              <1> 	; the file in the current directory or the root directory
  3605                              <1> 	; (if the first character of the pathname is '/').	
  3606                              <1> 	;
  3607                              <1> 	; INPUTS ->
  3608                              <1> 	;    u.namep - points to a file path name
  3609                              <1> 	;    u.cdir - i-number of users directory
  3610                              <1> 	;    u.cdev - device number on which user directory resides	
  3611                              <1> 	; OUTPUTS ->
  3612                              <1> 	;    r1 - i-number of file
  3613                              <1> 	;    cdev
  3614                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3615                              <1> 	;               occurs in the search for file path name.
  3616                              <1> 	;	        If no match u.dirb points to the end of 
  3617                              <1> 	;               the directory and r1 = i-number of the current
  3618                              <1> 	;	        directory.	
  3619                              <1> 	; ((AX = R1))
  3620                              <1> 	;
  3621                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3622                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3623                              <1> 	;
  3624                              <1> 
  3625 000049D4 66A1[506F0000]      <1> 	mov	ax, [u.cdir]
  3626                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3627                              <1> 			      ; / in r1
  3628                              <1> 	; 09/01/2022
  3629 000049DA 8A15[966F0000]      <1> 	mov	dl, [u.cdrv]
  3630 000049E0 8815[2F6F0000]      <1> 	mov	[cdev], dl
  3631                              <1> 	;mov	dx, [u.cdrv]
  3632                              <1> 	;mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3633                              <1> 				    ; device/drive number is in 1 byte, 
  3634                              <1> 				    ; not in 1 word!
  3635                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3636                              <1> 				; / into cdev
  3637                              <1> 	; 12/10/2015
  3638                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3639                              <1>       	 ; convert virtual (pathname) addr to physical address
  3640 000049E6 E868010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3641                              <1> 		; esi = physical address of [u.namep]
  3642                              <1> 		; ecx = byte count in the page
  3643 000049EB 803E2F              <1> 	cmp	byte [esi], '/'
  3644                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3645 000049EE 751D                <1> 	jne	short namei_1
  3646                              <1> 		; bne 1f
  3647 000049F0 FF05[646F0000]      <1> 	inc	dword [u.namep]
  3648                              <1> 		; inc u.namep / go to next char
  3649                              <1> 	;dec	cx ; remain byte count in the page
  3650                              <1> 	; 24/12/2021
  3651 000049F6 49                  <1> 	dec	ecx
  3652 000049F7 7506                <1> 	jnz	short namei_0
  3653                              <1> 	; 12/10/2015
  3654 000049F9 E855010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3655                              <1> 		; esi = physical address (page start + offset)
  3656                              <1> 		; ecx = byte count in the page
  3657 000049FE 4E                  <1> 	dec	esi
  3658                              <1> namei_0:
  3659 000049FF 46                  <1> 	inc 	esi  ; go to next char
  3660 00004A00 66A1[3A6F0000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3661                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3662 00004A06 C605[2F6F0000]00    <1> 	mov	byte [cdev], 0
  3663                              <1> 		; clr cdev / clear device number
  3664                              <1> namei_1: ; 1:
  3665 00004A0D F606FF              <1> 	test	byte [esi], 0FFh
  3666                              <1> namei_10: ; 24/12/2021 (jump from namei_8)
  3667 00004A10 74C1                <1> 	jz	short getf4
  3668                              <1> 	;jz	nig
  3669                              <1> 		; tstb *u.namep / is the character in file name a nul
  3670                              <1> 		; beq nig / yes, end of file name reached; 
  3671                              <1> 			; / branch to "nig"
  3672                              <1> namei_2: ; 1:
  3673                              <1> 	; 18/10/2015
  3674 00004A12 8935[C46F0000]      <1> 	mov 	[nbase], esi
  3675 00004A18 66890D[C86F0000]    <1> 	mov 	[ncount], cx
  3676                              <1> 	;
  3677                              <1> 	;mov	dx, 2
  3678 00004A1F B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3679 00004A21 E892080000          <1> 	call	access
  3680                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3681                              <1> 	; 'access' will not return here if user has not "r" permission !
  3682                              <1> 	; 03/02/2022
  3683 00004A26 F605[496C0000]40    <1> 	test	byte [i.flgs+1], 40h
  3684                              <1> 	;test 	word [i.flgs], 4000h
  3685                              <1> 		; bit $40000,i.flgs / directory i-node?
  3686 00004A2D 746A                <1>         jz      short namei_err
  3687                              <1> 		; beq error3 / no, got an error
  3688                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3689 00004A2F 31C0                <1> 	xor	eax, eax
  3690 00004A31 A3[686F0000]        <1> 	mov	[u.off], eax ; 0
  3691 00004A36 66A1[4C6C0000]      <1> 	mov	ax, [i.size]
  3692 00004A3C A3[606F0000]        <1> 	mov	[u.dirp], eax
  3693                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3694                              <1> 		; clr u.off / u.off is file offset used by user
  3695 00004A41 C705[5C6F0000]-     <1> 	mov	dword [u.fofp], u.off
  3695 00004A47 [686F0000]          <1>
  3696                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3697                              <1> 				  ; / the offset portion of fsp entry
  3698                              <1> namei_3: ; 2:
  3699 00004A4B C705[6C6F0000]-     <1> 	mov	dword [u.base], u.dirbuf
  3699 00004A51 [7E6F0000]          <1>
  3700                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3701                              <1> 				    ; / copied from a directory
  3702 00004A55 C705[706F0000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  3702 00004A5D 0000                <1>
  3703                              <1>  		; mov $10.,u.count / u.count is byte count 
  3704                              <1> 				 ; / for reads and writes
  3705 00004A5F 66A1[2C6F0000]      <1> 	mov 	ax, [ii]
  3706                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3707 00004A65 FE05[B36F0000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3708 00004A6B E848090000          <1>     	call	readi
  3709                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3710                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3711 00004A70 8B0D[746F0000]      <1> 	mov 	ecx, [u.nread]
  3712 00004A76 09C9                <1> 	or 	ecx, ecx
  3713                              <1> 		; tst u.nread
  3714 00004A78 741B                <1> 	jz	short nib
  3715                              <1> 		; ble nib / gives error return
  3716                              <1> 	;
  3717 00004A7A 668B1D[7E6F0000]    <1> 	mov 	bx, [u.dirbuf]
  3718 00004A81 6621DB              <1> 	and 	bx, bx       
  3719                              <1> 		; tst u.dirbuf /
  3720 00004A84 7522                <1> 	jnz	short namei_4
  3721                              <1> 		; bne 3f / branch when active directory entry 
  3722                              <1> 		       ; / (i-node word in entry non zero)
  3723 00004A86 A1[686F0000]        <1> 	mov	eax, [u.off]
  3724 00004A8B 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  3725 00004A8E A3[606F0000]        <1> 	mov	[u.dirp], eax
  3726                              <1> 		; mov u.off,u.dirp
  3727                              <1> 		; sub $10.,u.dirp
  3728 00004A93 EBB6                <1> 	jmp	short namei_3
  3729                              <1> 		; br 2b
  3730                              <1> 
  3731                              <1> 	; 18/07/2013
  3732                              <1> nib: 
  3733 00004A95 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3734 00004A97 F9                  <1> 	stc
  3735                              <1> nig:
  3736 00004A98 C3                  <1> 	retn
  3737                              <1> 
  3738                              <1> namei_err:
  3739                              <1> 	; 16/06/2015
  3740 00004A99 C705[A16F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3740 00004AA1 0000                <1>
  3741 00004AA3 E91FF0FFFF          <1> 	jmp	error
  3742                              <1> 
  3743                              <1> namei_4: ; 3:
  3744                              <1> 	; 18/10/2015
  3745                              <1> 	; 12/10/2015
  3746                              <1> 	; 21/08/2015
  3747                              <1> 	; 18/07/2015
  3748 00004AA8 8B2D[646F0000]      <1> 	mov	ebp, [u.namep]
  3749                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3750 00004AAE BF[806F0000]        <1> 	mov 	edi, u.dirbuf + 2
  3751                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3752                              <1> 	; 18/10/2015
  3753 00004AB3 8B35[C46F0000]      <1> 	mov	esi, [nbase]	
  3754 00004AB9 668B0D[C86F0000]    <1> 	mov	cx, [ncount]
  3755                              <1> 	;
  3756 00004AC0 6621C9              <1> 	and	cx, cx
  3757 00004AC3 7505                <1> 	jnz	short namei_5	
  3758                              <1> 	;
  3759 00004AC5 E88F000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3760                              <1> 		; esi = physical address (page start + offset)
  3761                              <1> 		; ecx = byte count in the page
  3762                              <1> namei_5: ; 3:
  3763 00004ACA 45                  <1> 	inc	ebp ; 18/07/2015
  3764 00004ACB AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3765                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3766 00004ACC 08C0                <1> 	or 	al, al
  3767 00004ACE 741C                <1> 	jz 	short namei_7
  3768                              <1> 		; beq 3f / if char is nul, then the last char in string
  3769                              <1> 			; / has been moved
  3770 00004AD0 3C2F                <1> 	cmp	al, '/'
  3771                              <1> 		; cmp r4,$'/ / is char a </>
  3772 00004AD2 7418                <1> 	je 	short namei_7
  3773                              <1> 		; beq 3f	
  3774                              <1> 	; 24/12/2021
  3775 00004AD4 49                  <1> 	dec	ecx
  3776                              <1> 	; 12/10/2015
  3777                              <1> 	;dec	cx ; remain byte count in the page
  3778 00004AD5 7505                <1> 	jnz	short namei_6
  3779 00004AD7 E87D000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3780                              <1> 		; esi = physical address (page start + offset)
  3781                              <1> 		; ecx = byte count in the page
  3782                              <1> namei_6:
  3783 00004ADC 81FF[8E6F0000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3784                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3785                              <1> 				     ; / all 8 bytes of file name
  3786 00004AE2 74E6                <1> 	je	short namei_5
  3787                              <1> 		; beq 3b
  3788 00004AE4 AE                  <1> 	scasb	
  3789                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3790                              <1> 			      ; / char read from directory
  3791 00004AE5 74E3                <1> 	je 	short namei_5
  3792                              <1> 		; beq 3b / branch if chars match
  3793                              <1> namei_9:
  3794 00004AE7 E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3795                              <1> 		; br 2b / file names do not match go to next directory entry
  3796                              <1> namei_7: ; 3:
  3797 00004AEC 81FF[8E6F0000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3798                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3799 00004AF2 7406                <1> 	je	short namei_8
  3800                              <1> 		; beq 3f
  3801 00004AF4 8A27                <1> 	mov 	ah, [edi]
  3802                              <1> 	;inc 	edi 
  3803 00004AF6 20E4                <1> 	and 	ah, ah
  3804                              <1> 		; tstb (r3)+ /
  3805                              <1>         ;jnz	namei_3
  3806                              <1> 		; bne 2b
  3807                              <1> 	; 24/12/2021
  3808 00004AF8 75ED                <1> 	jnz	short namei_9	
  3809                              <1> namei_8: ; 3
  3810 00004AFA 892D[646F0000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3811                              <1> 		; mov r2,u.namep / u.namep points to char 
  3812                              <1> 			       ; / following a / or nul
  3813                              <1> 	;mov	bx, [u.dirbuf]
  3814                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3815                              <1> 				; / entry to r1
  3816                              <1> 	;;;;
  3817                              <1> 	; 15/05/2022 - Retro UNIX (8086/386) feature only !
  3818                              <1> 	; ! 'pwd' utility modification !
  3819                              <1> 	; ((if directory entry name is a dotdot)))
  3820                              <1> 	;; check if it is mounted device's root directory inode
  3821                              <1> 	; and if so, replace it with parent dir inode number
  3822                              <1> 	;  of mounting directory in [mntp].
  3823                              <1> 
  3824 00004B00 668B1D[7E6F0000]    <1> 	mov	bx, [u.dirbuf]
  3825                              <1> 
  3826 00004B07 6683FB29            <1> 	cmp	bx, 41 ; root directory inode number
  3827 00004B0B 753C                <1> 	jne	short namei_11
  3828                              <1> 
  3829 00004B0D 663B1D[2C6F0000]    <1> 	cmp	bx, [ii] ; for root dir, '.' & '..' is 41
  3830 00004B14 7533                <1> 	jne	short namei_11 ; not root dir (of mounted dev)
  3831                              <1> 
  3832                              <1> 	;cmp	[idev], bh ; 0
  3833 00004B16 383D[2F6F0000]      <1> 	cmp	[cdev], bh ; 0
  3834                              <1> 			; 0 = root fs, dev num in [rdev]
  3835                              <1> 			; 1 = mounted, dev num in [mdev]
  3836 00004B1C 762B                <1> 	jna	short namei_11
  3837                              <1> 
  3838                              <1> 	; dotdot (parent directory link) check
  3839 00004B1E 66813D[806F0000]2E- <1> 	cmp	word [u.dirbuf+2], '..'
  3839 00004B26 2E                  <1>
  3840 00004B27 7520                <1> 	jne	short namei_11
  3841 00004B29 803D[826F0000]00    <1> 	cmp	byte [u.dirbuf+4], 0
  3842 00004B30 7517                <1> 	jne	short namei_11
  3843                              <1> 	
  3844                              <1> 	; (This may not be necessary because [idev] = 1
  3845                              <1> 	; and [mnti] is expected as a sub dir inode number)
  3846 00004B32 66391D[346F0000]    <1> 	cmp	[mnti], bx ; 41
  3847 00004B39 760E                <1> 	jna	short namei_11
  3848                              <1> 	
  3849                              <1> 	; change inumber to parent dir inum of mount directory
  3850 00004B3B 668B1D[366F0000]    <1> 	mov	bx, [mntp]
  3851 00004B42 C605[2F6F0000]00    <1> 	mov	byte [cdev], 0 ; root fs
  3852                              <1> namei_11:
  3853                              <1> 	;;;;
  3854                              <1> 
  3855 00004B49 20C0                <1> 	and 	al, al
  3856                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3857                              <1> 		      ;  / if r4 = </> then go to next directory
  3858                              <1> 	; 15/05/2022
  3859 00004B4B 6689D8              <1> 	mov	ax, bx
  3860                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  3861                              <1>   	; 24/12/2021
  3862 00004B4E E9BDFEFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3863                              <1> 	;jnz	namei_2 
  3864                              <1> 		; bne 1b
  3865                              <1> 	; AX = i-number of the file
  3866                              <1> ;;nig:
  3867                              <1> 	;retn	; 24/12/2021
  3868                              <1> 		; tst (r0)+ / gives non-error return
  3869                              <1> ;;nib:
  3870                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3871                              <1> 		       ; ax = 0 -> file not found 
  3872                              <1> ;;	stc	; 27/05/2013
  3873                              <1> ;;	retn
  3874                              <1> 		; rts r0
  3875                              <1> 
  3876                              <1> trans_addr_nmbp:
  3877                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3878                              <1> 	; 18/10/2015
  3879                              <1> 	; 12/10/2015
  3880 00004B53 8B2D[646F0000]      <1> 	mov 	ebp, [u.namep]
  3881                              <1> trans_addr_nm:
  3882                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 
  3883                              <1> 	; Convert virtual (pathname) address to physical address
  3884                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3885                              <1> 	; 18/10/2015
  3886                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3887                              <1> 	; 02/07/2015
  3888                              <1> 	; 17/06/2015
  3889                              <1> 	; 16/06/2015
  3890                              <1> 	;
  3891                              <1> 	; INPUTS: 
  3892                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3893                              <1> 	;	[u.pgdir] = user's page directory
  3894                              <1> 	; OUTPUT:
  3895                              <1> 	;       esi = physical address of the pathname
  3896                              <1> 	;	ecx = remain byte count in the page
  3897                              <1> 	;
  3898                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3899                              <1> 	;
  3900                              <1> 
  3901                              <1> 	; 08/01/2022
  3902 00004B59 29C9                <1> 	sub	ecx, ecx
  3903                              <1> 	;
  3904 00004B5B 833D[A96F0000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3905 00004B62 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3906                              <1> 				     ; it is already physical address
  3907 00004B64 50                  <1>    	push	eax	
  3908 00004B65 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3909 00004B67 E836E6FFFF          <1>        	call	get_physical_addr ; get physical address
  3910 00004B6C 7204                <1> 	jc	short tr_addr_nm_err
  3911                              <1> 	; 18/10/2015
  3912                              <1> 	; eax = physical address 
  3913                              <1> 	; cx = remain byte count in page (1-4096) 
  3914                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3915 00004B6E 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3916 00004B70 58                  <1> 	pop	eax 
  3917 00004B71 C3                  <1> 	retn
  3918                              <1> 
  3919                              <1> tr_addr_nm_err:
  3920 00004B72 A3[A16F0000]        <1> 	mov	[u.error], eax
  3921                              <1> 	;pop 	eax
  3922 00004B77 E94BEFFFFF          <1> 	jmp	error
  3923                              <1> 
  3924                              <1> trans_addr_nmk:
  3925                              <1> 	; 12/10/2015
  3926                              <1> 	; 02/07/2015
  3927 00004B7C 8B35[646F0000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3928                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3929                              <1> 	; 08/01/2022
  3930 00004B82 B510                <1> 	mov	ch, PAGE_SIZE/256
  3931 00004B84 C3                  <1> 	retn
  3932                              <1> 
  3933                              <1> syschdir:
  3934                              <1> 	; / makes the directory specified in the argument
  3935                              <1> 	; / the current directory
  3936                              <1> 	;
  3937                              <1> 	; 09/01/2022
  3938                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3939                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3940                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3941                              <1> 	;
  3942                              <1> 	; 'syschdir' makes the directory specified in its argument
  3943                              <1> 	; the current working directory.
  3944                              <1> 	;
  3945                              <1> 	; Calling sequence:
  3946                              <1> 	;	syschdir; name
  3947                              <1> 	; Arguments:
  3948                              <1> 	;	name - address of the path name of a directory
  3949                              <1> 	;	       terminated by nul byte.	
  3950                              <1> 	; Inputs: -
  3951                              <1> 	; Outputs: -
  3952                              <1> 	; ...............................................................
  3953                              <1> 	;				
  3954                              <1> 	; Retro UNIX 8086 v1 modification:
  3955                              <1> 	;	 The user/application program puts address of 
  3956                              <1> 	;	 the path name in BX register as 'syschdir' 
  3957                              <1> 	; 	 system call argument.
  3958                              <1> 
  3959 00004B85 891D[646F0000]      <1> 	mov	[u.namep], ebx
  3960                              <1> 		; jsr r0,arg; u.namep / u.namep points to path name
  3961 00004B8B E844FEFFFF          <1> 	call	namei
  3962                              <1> 		; jsr r0,namei / find its i-number
  3963                              <1> 	;jc	error
  3964                              <1> 		; br error3
  3965 00004B90 730F                <1> 	jnc	short syschdir0
  3966                              <1> 	; 'directory not found !' error
  3967 00004B92 C705[A16F0000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3967 00004B9A 0000                <1>
  3968 00004B9C E926EFFFFF          <1> 	jmp	error
  3969                              <1> syschdir0:
  3970                              <1> 	; 08/01/2022
  3971 00004BA1 B202                <1> 	mov	dl, 2  ; read access ; 08/01/2022 (BugFix)
  3972 00004BA3 E810070000          <1> 	call	access
  3973                              <1> 		; jsr r0,access; 2 / get i-node into core
  3974                              <1> 	; 08/01/2022
  3975 00004BA8 F605[496C0000]40    <1> 	test	byte [i.flgs+1], 40h
  3976                              <1> 	;test	word [i.flgs], 4000h
  3977                              <1> 		; bit $40000,i.flgs / is it a directory?
  3978                              <1> 	;jz	error 
  3979                              <1> 		; beq error3 / no error
  3980 00004BAF 750F                <1> 	jnz	short syschdir1
  3981 00004BB1 C705[A16F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3981 00004BB9 0000                <1>
  3982 00004BBB E907EFFFFF          <1> 	jmp	error
  3983                              <1> syschdir1:
  3984 00004BC0 66A3[506F0000]      <1> 	mov	[u.cdir], ax
  3985                              <1> 		; mov r1,u.cdir / move i-number to users 
  3986                              <1> 			      ; / current directory
  3987                              <1> 	; 09/01/2022
  3988 00004BC6 A0[2F6F0000]        <1> 	mov	al, [cdev]
  3989 00004BCB A2[966F0000]        <1> 	mov	[u.cdrv], al
  3990                              <1> 	;mov	ax, [cdev]
  3991                              <1> 	;mov	[u.cdrv], ax
  3992                              <1> 		; mov cdev,u.cdev / move its device to users 
  3993                              <1> 			        ; / current device
  3994 00004BD0 E912EFFFFF          <1> 	jmp	sysret
  3995                              <1> 		; br sysret3
  3996                              <1> 
  3997                              <1> syschmod: ; < change mode of file >
  3998                              <1> 	; 29/04/2022 (bugfix)
  3999                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4000                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4001                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4002                              <1> 	;
  4003                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  4004                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  4005                              <1> 	; changed to 'mode'.
  4006                              <1> 	;
  4007                              <1> 	; Calling sequence:
  4008                              <1> 	;	syschmod; name; mode
  4009                              <1> 	; Arguments:
  4010                              <1> 	;	name - address of the file name
  4011                              <1> 	;	       terminated by null byte.
  4012                              <1> 	;	mode - (new) mode/flags < attributes >
  4013                              <1> 	;	
  4014                              <1> 	; Inputs: -
  4015                              <1> 	; Outputs: -
  4016                              <1> 	; ...............................................................
  4017                              <1> 	;				
  4018                              <1> 	; Retro UNIX 8086 v1 modification: 
  4019                              <1> 	;       'syschmod' system call has two arguments; so,
  4020                              <1> 	;	* 1st argument, name is pointed to by BX register
  4021                              <1> 	;	* 2nd argument, mode is in CX register
  4022                              <1> 	;
  4023                              <1> 	; Mode bits (Flags):
  4024                              <1> 	;	bit 15 - 'i-node is allocated' flag (8000h)
  4025                              <1> 	;	bit 14 - directory flag (4000h)
  4026                              <1> 	;	bit 13 - file has modified flag (always on) (2000h)
  4027                              <1> 	;	bit 12 - large file flag (1000h)
  4028                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  4029                              <1> 	;	bit 5 - set user ID on execution flag (20h) 
  4030                              <1> 	;	bit 4 - executable flag (10h)
  4031                              <1> 	;	bit 3 - read permission for owner (08h)
  4032                              <1> 	;	bit 2 - write permission for owner (04h)
  4033                              <1> 	;	bit 1 - read permission for non-owner (02h)
  4034                              <1> 	;	bit 0 - write permission for non-owner (01h)
  4035                              <1> 
  4036                              <1> 	; / name; mode
  4037 00004BD5 E815000000          <1> 	call	isown
  4038                              <1> 		;jsr r0,isown / get the i-node and check user status
  4039                              <1> 	; 09/01/2022
  4040 00004BDA F605[496C0000]40    <1> 	test	byte [i.flgs+1], 40h
  4041                              <1> 	;test	word [i.flgs], 4000h
  4042                              <1> 		; bit $40000,i.flgs / directory?
  4043 00004BE1 7402                <1> 	jz	short syschmod1
  4044                              <1> 		; beq 2f / no
  4045                              <1> 	; AL = (new) mode
  4046 00004BE3 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  4047                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  4048                              <1> 			   ; / executable modes
  4049                              <1> syschmod1: ; 2:
  4050 00004BE5 A2[486C0000]        <1> 	mov	[i.flgs], al	
  4051                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  4052                              <1> 	;jmp	short isown1
  4053                              <1> 	;	; br 1f ; (jmp sysret4)
  4054                              <1> 	; 29/04/2022
  4055 00004BEA E9F8EEFFFF          <1> 	jmp	sysret
  4056                              <1> 
  4057                              <1> isown:
  4058                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4059                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4060                              <1> 	;
  4061                              <1> 	; 'isown' is given a file name (the 1st argument).
  4062                              <1> 	;  It find the i-number of that file via 'namei' 
  4063                              <1> 	;  then gets the i-node into core via 'iget'.
  4064                              <1> 	;  It then tests to see if the user is super user. 
  4065                              <1> 	;  If not, it cheks to see if the user is owner of 
  4066                              <1> 	;  the file. If he is not an error occurs.
  4067                              <1> 	;  If user is the owner 'setimod' is called to indicate
  4068                              <1> 	;  the inode has been modified and the 2nd argument of
  4069                              <1> 	;  the call is put in r2.
  4070                              <1> 	;
  4071                              <1> 	; INPUTS ->
  4072                              <1> 	;    arguments of syschmod and syschown calls
  4073                              <1> 	; OUTPUTS ->
  4074                              <1> 	;    u.uid - id of user
  4075                              <1> 	;    imod - set to a 1
  4076                              <1> 	;    r2 - contains second argument of the system call				 	
  4077                              <1> 	;
  4078                              <1> 	;   ((AX=R2) output as 2nd argument)
  4079                              <1> 	;
  4080                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4081                              <1> 	;
  4082                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4083                              <1> 	;; ! 2nd argument on top of stack !
  4084                              <1> 	;; 22/06/2015 - 32 bit modifications
  4085                              <1> 	;; 07/07/2013
  4086 00004BEF 891D[646F0000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4087 00004BF5 51                  <1> 	push 	ecx ;; 2nd argument
  4088                              <1> 	;;
  4089 00004BF6 E8D9FDFFFF          <1> 	call	namei
  4090                              <1> 		; jsr r0,namei / get its i-number
  4091                              <1>        ; Retro UNIX 8086 v1 modification !
  4092                              <1>        ; ax = 0 -> file not found 
  4093                              <1> 	;and	ax, ax
  4094                              <1> 	;jz	error
  4095                              <1> 	;jc	error ; 27/05/2013
  4096                              <1> 		; br error3
  4097 00004BFB 730F                <1> 	jnc	short isown0
  4098                              <1> 	; 'file not found !' error
  4099 00004BFD C705[A16F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4099 00004C05 0000                <1>
  4100 00004C07 E9BBEEFFFF          <1> 	jmp	error
  4101                              <1> isown0:
  4102 00004C0C E8D3050000          <1> 	call	iget
  4103                              <1> 		; jsr r0,iget / get i-node into core
  4104 00004C11 A0[986F0000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4105 00004C16 08C0                <1> 	or	al, al
  4106                              <1> 		; tstb u.uid / super user?
  4107 00004C18 7417                <1> 	jz	short isown1
  4108                              <1> 		; beq 1f / yes, branch
  4109 00004C1A 3A05[4B6C0000]      <1> 	cmp	al, [i.uid]
  4110                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4111                              <1> 				 ; / the file
  4112                              <1> 	;jne	error
  4113                              <1> 		; beq 1f / yes
  4114                              <1> 		; jmp error3 / no, error
  4115 00004C20 740F                <1> 	je	short isown1
  4116                              <1> 
  4117 00004C22 C705[A16F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4117 00004C2A 0000                <1>
  4118                              <1> 			;  'permission denied !' error
  4119 00004C2C E996EEFFFF          <1> 	jmp	error
  4120                              <1> isown1: ; 1:
  4121 00004C31 E8B8060000          <1> 	call	setimod
  4122                              <1> 		; jsr r0,setimod / indicates 
  4123                              <1> 		;	       ; / i-node has been modified
  4124 00004C36 58                  <1> 	pop	eax ; 2nd argument
  4125                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4126                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4127 00004C37 C3                  <1> 	retn
  4128                              <1> 		; rts r0
  4129                              <1> 
  4130                              <1> ;;arg:  ; < get system call arguments >
  4131                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4132                              <1> 	; of form:
  4133                              <1> 	;	sys 'routine' ; arg1
  4134                              <1> 	;		or
  4135                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4136                              <1> 	;		or
  4137                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4138                              <1> 	;	
  4139                              <1> 	; INPUTS ->
  4140                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4141                              <1> 	;	This pointers's value is actually the value of
  4142                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4143                              <1> 	;	made to process the sys instruction
  4144                              <1> 	;    r0 - contains the return address for the routine
  4145                              <1> 	;	that called arg. The data in the word pointer 
  4146                              <1> 	;	to by the return address is used as address
  4147                              <1> 	;	in which the extracted argument is stored   		
  4148                              <1> 	;    	
  4149                              <1> 	; OUTPUTS ->
  4150                              <1> 	;    'address' - contains the extracted argument 
  4151                              <1> 	;    u.sp+18 - is incremented by 2 
  4152                              <1> 	;    r1 - contains the extracted argument
  4153                              <1> 	;    r0 - points to the next instruction to be
  4154                              <1> 	;	 executed in the calling routine.
  4155                              <1> 	;
  4156                              <1>   
  4157                              <1> 	; mov u.sp,r1
  4158                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4159                              <1> 			; / into argument of arg2
  4160                              <1> 	; add $2,18.(r1) / point pc on stack 
  4161                              <1> 			      ; / to next system argument
  4162                              <1> 	; rts r0
  4163                              <1> 
  4164                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4165                              <1> 	; 'arg2' takes first argument in system call
  4166                              <1> 	;  (pointer to name of the file) and puts it in location
  4167                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4168                              <1> 	;  and on top of the stack
  4169                              <1> 	;	
  4170                              <1> 	; INPUTS ->
  4171                              <1> 	;    u.sp, r0
  4172                              <1> 	;    	
  4173                              <1> 	; OUTPUTS ->
  4174                              <1> 	;    u.namep
  4175                              <1> 	;    u.off 
  4176                              <1> 	;    u.off pushed on stack
  4177                              <1> 	;    r1
  4178                              <1> 	;
  4179                              <1> 
  4180                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4181                              <1> 				; / first arg in sys call
  4182                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4183                              <1> 				; / second arg in sys call
  4184                              <1> 	; mov r0,r1 / r0 points to calling routine
  4185                              <1> 	; mov (sp),r0 / put operation code back in r0
  4186                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4187                              <1> 			; / on stack
  4188                              <1> 	; jmp (r1) / return to calling routine
  4189                              <1> 
  4190                              <1> syschown: ; < change owner of file >
  4191                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4192                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4193                              <1> 	;
  4194                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4195                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4196                              <1> 	; changed to 'owner'
  4197                              <1> 	;
  4198                              <1> 	; Calling sequence:
  4199                              <1> 	;	syschown; name; owner
  4200                              <1> 	; Arguments:
  4201                              <1> 	;	name - address of the file name
  4202                              <1> 	;	       terminated by null byte.
  4203                              <1> 	;	owner - (new) owner (number/ID)
  4204                              <1> 	;	
  4205                              <1> 	; Inputs: -
  4206                              <1> 	; Outputs: -
  4207                              <1> 	; ...............................................................
  4208                              <1> 	;				
  4209                              <1> 	; Retro UNIX 8086 v1 modification: 
  4210                              <1> 	;       'syschown' system call has two arguments; so,
  4211                              <1> 	;	* 1st argument, name is pointed to by BX register
  4212                              <1> 	;	* 2nd argument, owner number is in CX register
  4213                              <1> 	;
  4214                              <1> 	; / name; owner
  4215 00004C38 E8B2FFFFFF          <1> 	call	isown
  4216                              <1> 		; jsr r0,isown / get the i-node and check user status
  4217 00004C3D 803D[986F0000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4218                              <1> 		; tstb u.uid / super user
  4219 00004C44 7418                <1> 	jz	short syschown1
  4220                              <1> 		; beq 2f / yes, 2f
  4221 00004C46 F605[486C0000]20    <1>         test    byte [i.flgs], 20h ; 32
  4222                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4223                              <1> 	;jnz	error
  4224                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4225 00004C4D 740F                <1> 	jz	short syschown1
  4226                              <1> 	; 'permission denied !'
  4227 00004C4F C705[A16F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4227 00004C57 0000                <1>
  4228 00004C59 E969EEFFFF          <1> 	jmp	error
  4229                              <1> syschown1: ; 2:
  4230                              <1> 	; AL = owner (number/ID)
  4231 00004C5E A2[4B6C0000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4232                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4233                              <1> 			       ; / in the i-node
  4234 00004C63 E97FEEFFFF          <1> 	jmp	sysret
  4235                              <1> 	; 1: 
  4236                              <1> 		; jmp sysret4
  4237                              <1> 	; 3:
  4238                              <1> 		; jmp	error
  4239                              <1> 
  4240                              <1> systime: ; / get time of year
  4241                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4242                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4243                              <1> 	;
  4244                              <1> 	; 20/06/2013
  4245                              <1> 	; 'systime' gets the time of the year.
  4246                              <1> 	; The present time is put on the stack.
  4247                              <1> 	;
  4248                              <1> 	; Calling sequence:
  4249                              <1> 	;	systime
  4250                              <1> 	; Arguments: -
  4251                              <1> 	;	
  4252                              <1> 	; Inputs: -
  4253                              <1> 	; Outputs: sp+2, sp+4 - present time
  4254                              <1> 	; ...............................................................
  4255                              <1> 	;	
  4256                              <1> 	; Retro UNIX 8086 v1 modification: 
  4257                              <1> 	;       'systime' system call will return to the user
  4258                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4259                              <1> 	;
  4260                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4261                              <1> 	;	system call for PC compatibility !!		 	
  4262                              <1> 
  4263 00004C68 E8A8E9FFFF          <1> 	call 	epoch
  4264 00004C6D A3[4C6F0000]        <1> 	mov 	[u.r0], eax
  4265                              <1> 		; mov s.time,4(sp)
  4266                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4267                              <1> 				   ; / on the stack
  4268                              <1> 		; br sysret4
  4269 00004C72 E970EEFFFF          <1> 	jmp	sysret 
  4270                              <1> 
  4271                              <1> sysstime: ; / set time
  4272                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4273                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4274                              <1> 	;
  4275                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4276                              <1> 	;
  4277                              <1> 	; Calling sequence:
  4278                              <1> 	;	sysstime
  4279                              <1> 	; Arguments: -
  4280                              <1> 	;	
  4281                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4282                              <1> 	; Outputs: -
  4283                              <1> 	; ...............................................................
  4284                              <1> 	;	
  4285                              <1> 	; Retro UNIX 8086 v1 modification: 
  4286                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4287                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4288                              <1> 	; 
  4289                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4290                              <1> 	;	to get sysstime system call arguments from the user;
  4291                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4292                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4293                              <1> 	;
  4294                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4295                              <1> 	;	system call for PC compatibility !!	
  4296                              <1> 
  4297 00004C77 803D[986F0000]00    <1> 	cmp	byte [u.uid], 0
  4298                              <1> 		; tstb u.uid / is user the super user
  4299                              <1> 	;ja	error
  4300                              <1> 		; bne error4 / no, error
  4301 00004C7E 760F                <1> 	jna	short systime1
  4302                              <1> 	; 'permission denied !'
  4303 00004C80 C705[A16F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4303 00004C88 0000                <1>
  4304 00004C8A E938EEFFFF          <1> 	jmp	error
  4305                              <1> systime1:
  4306                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4307                              <1> 	; EBX = unix (epoch) time (from user)
  4308 00004C8F 89D8                <1> 	mov	eax, ebx
  4309 00004C91 E8FFEAFFFF          <1> 	call 	set_date_time
  4310                              <1> 		; mov 4(sp),s.time
  4311                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4312 00004C96 E94CEEFFFF          <1> 	jmp	sysret
  4313                              <1> 		; br sysret4
  4314                              <1> 
  4315                              <1> sysbreak:
  4316                              <1> 	; 18/10/2015
  4317                              <1> 	; 07/10/2015
  4318                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4319                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4320                              <1> 	;
  4321                              <1> 	; 'sysbreak' sets the programs break points. 
  4322                              <1> 	; It checks the current break point (u.break) to see if it is
  4323                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4324                              <1> 	; even address (if it was odd) and the area between u.break
  4325                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4326                              <1> 	; in u.break and control is passed to 'sysret'.
  4327                              <1> 	;
  4328                              <1> 	; Calling sequence:
  4329                              <1> 	;	sysbreak; addr
  4330                              <1> 	; Arguments: -
  4331                              <1> 	;	
  4332                              <1> 	; Inputs: u.break - current breakpoint
  4333                              <1> 	; Outputs: u.break - new breakpoint 
  4334                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4335                              <1> 	; ...............................................................
  4336                              <1> 	;	
  4337                              <1> 	; Retro UNIX 8086 v1 modification:
  4338                              <1> 	;	The user/application program puts breakpoint address
  4339                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4340                              <1> 	; 	(argument transfer method 1)
  4341                              <1> 	;
  4342                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4343                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4344                              <1> 	;  NOTE:
  4345                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4346                              <1> 	;	'u.break' address) of user's memory for original unix's
  4347                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4348                              <1> 
  4349                              <1> 		; mov u.break,r1 / move users break point to r1
  4350                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4351                              <1> 		; blos 1f / yes, 1f
  4352                              <1> 	; 23/06/2015
  4353 00004C9B 8B2D[786F0000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4354                              <1> 	;and	ebp, ebp
  4355                              <1> 	;jz	short sysbreak_3 
  4356                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4357                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4358 00004CA1 8B15[446F0000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4359 00004CA7 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4360                              <1> 	; 07/10/2015
  4361 00004CAA 891D[786F0000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4362                              <1> 	;
  4363 00004CB0 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4364                              <1> 			   ; with top of user's stack (virtual!)
  4365 00004CB2 7327                <1> 	jnb	short sysbreak_3
  4366                              <1> 		; cmp r1,sp / is it the same or higher 
  4367                              <1> 			  ; / than the stack?
  4368                              <1> 		; bhis 1f / yes, 1f
  4369 00004CB4 89DE                <1> 	mov	esi, ebx
  4370 00004CB6 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4371 00004CB8 7621                <1> 	jna	short sysbreak_3 
  4372                              <1> 	;push	ebx
  4373                              <1> sysbreak_1:
  4374 00004CBA 89EB                <1> 	mov	ebx, ebp  
  4375 00004CBC E8E1E4FFFF          <1> 	call	get_physical_addr ; get physical address
  4376 00004CC1 0F82ABFEFFFF        <1> 	jc	tr_addr_nm_err
  4377                              <1> 	; 18/10/2015
  4378 00004CC7 89C7                <1> 	mov	edi, eax 
  4379 00004CC9 29C0                <1> 	sub	eax, eax ; 0
  4380                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4381 00004CCB 39CE                <1> 	cmp	esi, ecx
  4382 00004CCD 7302                <1> 	jnb	short sysbreak_2
  4383 00004CCF 89F1                <1> 	mov	ecx, esi
  4384                              <1> sysbreak_2:
  4385 00004CD1 29CE                <1> 	sub	esi, ecx
  4386 00004CD3 01CD                <1> 	add	ebp, ecx
  4387 00004CD5 F3AA                <1> 	rep 	stosb
  4388 00004CD7 09F6                <1> 	or	esi, esi
  4389 00004CD9 75DF                <1> 	jnz	short sysbreak_1
  4390                              <1> 	;
  4391                              <1> 		; bit $1,r1 / is it an odd address
  4392                              <1> 		; beq 2f / no, its even
  4393                              <1> 		; clrb (r1)+ / yes, make it even
  4394                              <1> 	; 2: / clear area between the break point and the stack
  4395                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4396                              <1> 		; bhis 1f / yes, quit
  4397                              <1> 		; clr (r1)+ / clear word
  4398                              <1> 		; br 2b / go back
  4399                              <1> 	;pop	ebx
  4400                              <1> sysbreak_3: ; 1:
  4401                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4402                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4403                              <1> 			; / in u.break (set new break point)
  4404                              <1> 		; br sysret4 / br sysret
  4405 00004CDB E907EEFFFF          <1> 	jmp	sysret
  4406                              <1> 
  4407                              <1> maknod: 
  4408                              <1> 	; 11/02/2022
  4409                              <1> 	; 09/01/2022
  4410                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4411                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4412                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4413                              <1> 	;
  4414                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4415                              <1> 	; for this i-node in the current directory.
  4416                              <1> 	;
  4417                              <1> 	; INPUTS ->
  4418                              <1> 	;    r1 - contains mode
  4419                              <1> 	;    ii - current directory's i-number	
  4420                              <1> 	;    	
  4421                              <1> 	; OUTPUTS ->
  4422                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4423                              <1> 	;    i.flgs - flags in new i-node 
  4424                              <1> 	;    i.uid - filled with u.uid
  4425                              <1> 	;    i.nlks - 1 is put in the number of links
  4426                              <1> 	;    i.ctim - creation time				
  4427                              <1> 	;    i.ctim+2 - modification time
  4428                              <1> 	;    imod - set via call to setimod
  4429                              <1> 	;	
  4430                              <1> 	; ((AX = R1)) input
  4431                              <1> 	;
  4432                              <1> 	; (Retro UNIX Prototype : 
  4433                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4434                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4435                              <1> 
  4436                              <1> 	; / r1 contains the mode
  4437 00004CE0 80CC80              <1> 	or 	ah, 80h	; 10000000b
  4438                              <1> 		; bis $100000,r1 / allocate flag set
  4439 00004CE3 6650                <1> 	push	ax ; * ; 24/12/2021
  4440                              <1> 		; mov r1,-(sp) / put mode on stack
  4441                              <1> 	; 31/07/2013
  4442 00004CE5 66A1[2C6F0000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4443                              <1> 		; mov ii,r1 / move current i-number to r1
  4444 00004CEB B201                <1> 	mov	dl, 1 ; owner flag mask
  4445 00004CED E8C6050000          <1> 	call	access	
  4446                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4447 00004CF2 50                  <1> 	push	eax ; ** ; 24/12/2021
  4448                              <1> 		; mov r1,-(sp) / put i-number on stack
  4449 00004CF3 66B82800            <1> 	mov	ax, 40
  4450                              <1> 		; mov $40.,r1 / r1 = 40
  4451                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4452 00004CF7 6640                <1> 	inc	ax
  4453                              <1> 		; inc r1 / r1 = r1 + 1
  4454 00004CF9 E87F060000          <1> 	call	imap
  4455                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4456                              <1> 			    ; /	inode map in r2 & m
  4457                              <1>   
  4458                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4459                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4460                              <1> 
  4461                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4462                              <1> 	;	       Inode count must be checked here
  4463                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4464                              <1> 
  4465                              <1> 	; 11/02/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  4466                              <1> 	; (inode count check)
  4467                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4468                              <1> 
  4469 00004CFE 730F                <1> 	jnc	short maknod2
  4470                              <1> 
  4471                              <1> 	; no free inode in inode table !
  4472 00004D00 C705[A16F0000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4472 00004D08 0000                <1>
  4473                              <1> 			; miscellaneous/other errors
  4474 00004D0A E9B8EDFFFF          <1> 	jmp	error	
  4475                              <1> maknod2: 
  4476 00004D0F 8413                <1> 	test	[ebx], dl
  4477                              <1> 		; bitb mq,(r2) / is the i-node active
  4478 00004D11 75E4                <1> 	jnz	short maknod1
  4479                              <1> 		; bne 1b / yes, try the next one
  4480 00004D13 0813                <1> 	or	[ebx], dl
  4481                              <1> 		; bisb mq,(r2) / no, make it active 
  4482                              <1> 			     ; / (put a 1 in the bit map)
  4483 00004D15 E8CA040000          <1> 	call	iget
  4484                              <1> 		; jsr r0,iget / get i-node into core
  4485                              <1> 	; 09/01/2022
  4486 00004D1A F605[496C0000]80    <1> 	test	byte [i.flgs+1], 80h
  4487                              <1> 	;test	word [i.flgs], 8000h 
  4488                              <1> 		; tst i.flgs / is i-node already allocated
  4489 00004D21 75D4                <1> 	jnz	short maknod1	
  4490                              <1> 		; blt 1b / yes, look for another one
  4491 00004D23 66A3[7E6F0000]      <1> 	mov	[u.dirbuf], ax
  4492                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4493 00004D29 58                  <1> 	pop	eax ; ** ; 24/12/2021
  4494                              <1> 		; mov (sp)+,r1 / get current i-number back
  4495 00004D2A E8B5040000          <1> 	call	iget
  4496                              <1> 		; jsr r0,iget / get i-node in core
  4497 00004D2F E857F7FFFF          <1> 	call	mkdir
  4498                              <1> 		; jsr r0,mkdir / make a directory entry 
  4499                              <1> 			     ; / in current directory
  4500 00004D34 66A1[7E6F0000]      <1> 	mov	ax, [u.dirbuf]
  4501                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4502 00004D3A E8A5040000          <1> 	call	iget
  4503                              <1> 		; jsr r0,iget / get it into core
  4504                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4505                              <1> 	;mov	ecx, 8
  4506                              <1> 	; 09/01/2022 
  4507 00004D3F 29C9                <1> 	sub	ecx, ecx
  4508 00004D41 B108                <1> 	mov	cl, 8
  4509 00004D43 31C0                <1> 	xor	eax, eax ; 0
  4510 00004D45 BF[486C0000]        <1> 	mov	edi, inode 
  4511 00004D4A F3AB                <1> 	rep	stosd
  4512                              <1> 	;
  4513 00004D4C 668F05[486C0000]    <1> 	pop	word [i.flgs] ; * ; 24/12/2021
  4514                              <1> 		; mov (sp)+,i.flgs / fill flags
  4515 00004D53 8A0D[986F0000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4516 00004D59 880D[4B6C0000]      <1> 	mov 	[i.uid], cl
  4517                              <1> 		; movb u.uid,i.uid / user id	
  4518 00004D5F C605[4A6C0000]01    <1> 	mov     byte [i.nlks], 1
  4519                              <1> 		; movb $1,i.nlks / 1 link
  4520                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4521                              <1> 	;mov	eax, [s.time]
  4522                              <1> 	;mov 	[i.ctim], eax
  4523                              <1> 	 	; mov s.time,i.ctim / time created
  4524                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4525                              <1> 	; Retro UNIX 8086 v1 modification !
  4526                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4527                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4528                              <1> 	;call	setimod
  4529                              <1> 	;	; jsr r0,setimod / set modified flag
  4530                              <1> 	;retn
  4531                              <1> 	;	; rts r0 / return
  4532                              <1> 	; 24/12/2021
  4533 00004D66 E983050000          <1> 	jmp	setimod
  4534                              <1> 
  4535                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4536                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4537                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4538                              <1> 	;
  4539                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4540                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4541                              <1> 	; The file descriptor refers to a file open for reading or
  4542                              <1> 	; writing. The read (or write) pointer is set as follows:
  4543                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4544                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4545                              <1> 	;	  current location plus offset.
  4546                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4547                              <1> 	;	  size of file plus offset.
  4548                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4549                              <1> 	;
  4550                              <1> 	; Calling sequence:
  4551                              <1> 	;	sysseek; offset; ptrname
  4552                              <1> 	; Arguments:
  4553                              <1> 	;	offset - number of bytes desired to move 
  4554                              <1> 	;		 the r/w pointer
  4555                              <1> 	;	ptrname - a switch indicated above
  4556                              <1> 	;
  4557                              <1> 	; Inputs: r0 - file descriptor 
  4558                              <1> 	; Outputs: -
  4559                              <1> 	; ...............................................................
  4560                              <1> 	;	
  4561                              <1> 	; Retro UNIX 8086 v1 modification: 
  4562                              <1> 	;       'sysseek' system call has three arguments; so,
  4563                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4564                              <1> 	;	* 2nd argument, offset is in CX register
  4565                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4566                              <1> 	;	
  4567                              <1> 
  4568 00004D6B E822000000          <1> 	call	seektell
  4569                              <1> 	; AX = u.count
  4570                              <1> 	; BX = *u.fofp
  4571                              <1> 		; jsr r0,seektell / get proper value in u.count
  4572                              <1> 		; add u.base,u.count / add u.base to it
  4573 00004D70 0305[6C6F0000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4574 00004D76 8903                <1> 	mov	[ebx], eax
  4575                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4576 00004D78 E96AEDFFFF          <1> 	jmp	sysret
  4577                              <1> 		; br sysret4
  4578                              <1> 
  4579                              <1> systell: ; / get the r/w pointer
  4580                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4581                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4582                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4583                              <1> 	;
  4584                              <1> 	; Retro UNIX 8086 v1 modification:
  4585                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4586                              <1> 	; 	    it returns with error !
  4587                              <1> 	; Inputs: r0 - file descriptor 
  4588                              <1> 	; Outputs: r0 - file r/w pointer
  4589                              <1> 
  4590                              <1> 	;xor	ecx, ecx ; 0
  4591                              <1> 	;mov	edx, 1 ; 05/08/2013
  4592                              <1> 	; 24/12/2021
  4593 00004D7D 29D2                <1> 	sub	edx, edx
  4594 00004D7F FEC2                <1> 	inc	dl
  4595                              <1> 	; edx = 1
  4596                              <1> 	;call 	seektell
  4597 00004D81 E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4598                              <1> 	;mov	ebx, [u.fofp]
  4599 00004D86 8B03                <1> 	mov	eax, [ebx]
  4600 00004D88 A3[4C6F0000]        <1> 	mov	[u.r0], eax
  4601 00004D8D E955EDFFFF          <1> 	jmp	sysret
  4602                              <1> 
  4603                              <1> ; Original unix v1 'systell' system call:
  4604                              <1> 		; jsr r0,seektell
  4605                              <1> 		; br error4
  4606                              <1> 
  4607                              <1> seektell:
  4608                              <1> 	; 03/02/2022
  4609                              <1> 	; 03/01/2016
  4610                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4611                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4612                              <1> 	;
  4613                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4614                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4615                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4616                              <1> 	; getf. The i-node is brought into core and then u.count
  4617                              <1> 	; is checked to see it is a 0, 1, or 2.
  4618                              <1> 	; If it is 0 - u.count stays the same
  4619                              <1> 	;          1 - u.count = offset (u.fofp)
  4620                              <1> 	;	   2 - u.count = i.size (size of file)
  4621                              <1> 	; 	 		
  4622                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4623                              <1> 	;	Argument 1, file descriptor is in BX;
  4624                              <1> 	;	Argument 2, offset is in CX;
  4625                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4626                              <1> 	;
  4627                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4628                              <1> 	; call 	arg
  4629                              <1> 	;
  4630                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4631                              <1> 	;
  4632 00004D92 890D[6C6F0000]      <1> 	mov 	[u.base], ecx ; offset
  4633                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4634                              <1> seektell0:
  4635 00004D98 8915[706F0000]      <1> 	mov 	[u.count], edx
  4636                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4637                              <1> 	; mov	ax, bx
  4638                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4639                              <1> 			     ; / (index in u.fp list)
  4640                              <1> 	; call	getf
  4641                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4642                              <1> 	; BX = file descriptor (file number)
  4643 00004D9E E800FCFFFF          <1> 	call	getf1
  4644                              <1> 	; 03/02/2022
  4645 00004DA3 09C0                <1> 	or	eax, eax
  4646                              <1> 	;or	ax, ax ; i-number of the file
  4647                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4648                              <1> 		             ; / put it on the stack
  4649                              <1> 	;jz	error
  4650                              <1> 		; beq error4 / if i-number is 0, not active so error
  4651 00004DA5 750F                <1> 	jnz	short seektell1
  4652 00004DA7 C705[A16F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4652 00004DAF 0000                <1>
  4653 00004DB1 E911EDFFFF          <1> 	jmp	error
  4654                              <1> seektell1:
  4655                              <1> 	;push	eax
  4656 00004DB6 80FC80              <1> 	cmp	ah, 80h
  4657 00004DB9 7203                <1> 	jb	short seektell2
  4658                              <1> 		; bgt .+4 / if its positive jump
  4659 00004DBB 66F7D8              <1> 	neg	ax
  4660                              <1> 		; neg r1 / if not make it positive
  4661                              <1> seektell2:
  4662 00004DBE E821040000          <1> 	call	iget
  4663                              <1> 		; jsr r0,iget / get its i-node into core
  4664 00004DC3 8B1D[5C6F0000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4665 00004DC9 803D[706F0000]01    <1> 	cmp	byte [u.count], 1
  4666                              <1> 		; cmp u.count,$1 / is ptr name =1
  4667 00004DD0 7705                <1> 	ja	short seektell3
  4668                              <1> 		; blt 2f / no its zero
  4669 00004DD2 740A                <1> 	je	short seektell_4
  4670                              <1> 		; beq 1f / yes its 1
  4671 00004DD4 31C0                <1> 	xor	eax, eax
  4672                              <1> 	;jmp	short seektell_5
  4673 00004DD6 C3                  <1> 	retn
  4674                              <1> seektell3:
  4675                              <1> 	; 03/01/2016
  4676                              <1> 	;movzx	eax, word [i.size]
  4677 00004DD7 66A1[4C6C0000]      <1>         mov   	ax, [i.size]
  4678                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4679                              <1>                                    ; / in file in u.count
  4680                              <1> 	;jmp	short seektell_5
  4681                              <1> 		; br 2f
  4682 00004DDD C3                  <1> 	retn
  4683                              <1> seektell_4: ; 1: / ptrname =1
  4684                              <1> 	;mov	ebx, [u.fofp]
  4685 00004DDE 8B03                <1> 	mov	eax, [ebx]
  4686                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4687                              <1> ;seektell_5: ; 2: / ptrname =0
  4688                              <1> 	;mov	[u.count], eax
  4689                              <1> 	;pop	eax 
  4690                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4691 00004DE0 C3                  <1> 	retn
  4692                              <1> 		; rts r0
  4693                              <1> 
  4694                              <1> sysintr: ; / set interrupt handling
  4695                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4696                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4697                              <1> 	;
  4698                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4699                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4700                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4701                              <1> 	; If one does the interrupt character in the tty buffer is
  4702                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4703                              <1> 	; 'sysret' is just called.	
  4704                              <1> 	;
  4705                              <1> 	; Calling sequence:
  4706                              <1> 	;	sysintr; arg
  4707                              <1> 	; Argument:
  4708                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4709                              <1> 	;	    - if 1, intterupts cause their normal result
  4710                              <1> 	;		 i.e force an exit.
  4711                              <1> 	;	    - if arg is a location within the program,
  4712                              <1> 	;		control is passed to that location when
  4713                              <1> 	;		an interrupt occurs.	
  4714                              <1> 	; Inputs: -
  4715                              <1> 	; Outputs: -
  4716                              <1> 	; ...............................................................
  4717                              <1> 	;	
  4718                              <1> 	; Retro UNIX 8086 v1 modification: 
  4719                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4720                              <1> 	;	then branches into sysquit.
  4721                              <1> 	;
  4722 00004DE1 66891D[906F0000]    <1> 	mov	[u.intr], bx
  4723                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4724                              <1> 		; br 1f / go into quit routine
  4725 00004DE8 E9FAECFFFF          <1> 	jmp	sysret
  4726                              <1> 
  4727                              <1> sysquit:
  4728                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4729                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4730                              <1> 	;
  4731                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4732                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4733                              <1> 	; tty exists. If one does the interrupt character in the tty
  4734                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4735                              <1> 	; 'sysret' is just called.	
  4736                              <1> 	;
  4737                              <1> 	; Calling sequence:
  4738                              <1> 	;	sysquit; arg
  4739                              <1> 	; Argument:
  4740                              <1> 	;	arg - if 0, this call diables quit signals from the
  4741                              <1> 	;		typewriter (ASCII FS)
  4742                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4743                              <1> 	;		cease and a core image to be produced.
  4744                              <1> 	;		 i.e force an exit.
  4745                              <1> 	;	    - if arg is an addres in the program,
  4746                              <1> 	;		a quit causes control to sent to that
  4747                              <1> 	;		location.	
  4748                              <1> 	; Inputs: -
  4749                              <1> 	; Outputs: -
  4750                              <1> 	; ...............................................................
  4751                              <1> 	;	
  4752                              <1> 	; Retro UNIX 8086 v1 modification: 
  4753                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4754                              <1> 	;	then branches into 'sysret'.
  4755                              <1> 	;
  4756 00004DED 66891D[926F0000]    <1> 	mov	[u.quit], bx
  4757 00004DF4 E9EEECFFFF          <1> 	jmp	sysret
  4758                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4759                              <1> 	;1:
  4760                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4761                              <1> 			      ; / to r1
  4762                              <1> 		; beq sysret4 / return to user
  4763                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4764                              <1> 			   ; / in the tty buffer
  4765                              <1> 		; br sysret4 / return to user
  4766                              <1> 
  4767                              <1> syssetuid: ; / set process id
  4768                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4769                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4770                              <1> 	;
  4771                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4772                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4773                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4774                              <1> 	; Only the super user can make this call.	
  4775                              <1> 	;
  4776                              <1> 	; Calling sequence:
  4777                              <1> 	;	syssetuid
  4778                              <1> 	; Arguments: -
  4779                              <1> 	;
  4780                              <1> 	; Inputs: (u.r0) - contains the process id.
  4781                              <1> 	; Outputs: -
  4782                              <1> 	; ...............................................................
  4783                              <1> 	;	
  4784                              <1> 	; Retro UNIX 8086 v1 modification: 
  4785                              <1> 	;       BL contains the (new) user ID of the current process
  4786                              <1> 
  4787                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4788 00004DF9 3A1D[996F0000]      <1> 	cmp	bl, [u.ruid] 
  4789                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4790                              <1> 			       ; / id number
  4791 00004DFF 741E                <1> 	je	short setuid1
  4792                              <1> 		; beq 1f / yes
  4793 00004E01 803D[986F0000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4794                              <1> 		; tstb u.uid / no, is current user the super user?
  4795                              <1> 	;ja	error
  4796                              <1> 		; bne error4 / no, error
  4797 00004E08 760F                <1> 	jna	short setuid0
  4798 00004E0A C705[A16F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4798 00004E12 0000                <1>
  4799                              <1> 				; 'permission denied !' error
  4800 00004E14 E9AEECFFFF          <1> 	jmp	error
  4801                              <1> setuid0:
  4802 00004E19 881D[996F0000]      <1> 	mov	[u.ruid], bl
  4803                              <1> setuid1: ; 1:
  4804 00004E1F 881D[986F0000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4805                              <1> 		; movb r1,u.uid / put process id in u.uid
  4806                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4807 00004E25 E9BDECFFFF          <1> 	jmp	sysret
  4808                              <1> 		; br sysret4 / system return
  4809                              <1> 
  4810                              <1> sysgetuid: ; < get user id >
  4811                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4812                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4813                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4814                              <1> 	;
  4815                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4816                              <1> 	; The real user ID identifies the person who is logged in,
  4817                              <1> 	; in contradistinction to the effective user ID, which
  4818                              <1> 	; determines his access permission at each moment. It is thus
  4819                              <1> 	; useful to programs which operate using the 'set user ID'
  4820                              <1> 	; mode, to find out who invoked them.	
  4821                              <1> 	;
  4822                              <1> 	; Calling sequence:
  4823                              <1> 	;	syssetuid
  4824                              <1> 	; Arguments: -
  4825                              <1> 	;
  4826                              <1> 	; Inputs: -
  4827                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4828                              <1> 	; ...............................................................
  4829                              <1> 	;	
  4830                              <1> 	; Retro UNIX 8086 v1 modification: 
  4831                              <1> 	;       AL contains the real user ID at return.
  4832                              <1> 	;
  4833                              <1> 	;movzx 	eax, byte [u.ruid]
  4834                              <1> 	; 09/01/2022
  4835 00004E2A A0[996F0000]        <1> 	mov	al, [u.ruid]
  4836 00004E2F A3[4C6F0000]        <1> 	mov	[u.r0], eax
  4837                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4838 00004E34 E9AEECFFFF          <1> 	jmp	sysret
  4839                              <1> 		; br sysret4 / systerm return, sysret
  4840                              <1> 
  4841                              <1> anyi: 
  4842                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4843                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4844                              <1> 	;
  4845                              <1> 	; 'anyi' is called if a file deleted while open.
  4846                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4847                              <1> 	;
  4848                              <1> 	; INPUTS ->
  4849                              <1> 	;    r1 - contains an i-number
  4850                              <1> 	;    fsp - start of table containing open files
  4851                              <1> 	;
  4852                              <1> 	; OUTPUTS ->
  4853                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4854                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4855                              <1> 	;    if file not found - bit in i-node map is cleared
  4856                              <1> 	;    			 (i-node is freed)
  4857                              <1> 	;               all blocks related to i-node are freed
  4858                              <1> 	;	        all flags in i-node are cleared
  4859                              <1> 	; ((AX = R1)) input
  4860                              <1> 	;
  4861                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4862                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4863                              <1> 	;
  4864                              <1> 		; / r1 contains an i-number
  4865 00004E39 BB[186D0000]        <1> 	mov	ebx, fsp
  4866                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4867                              <1> anyi_1: ; 1:
  4868 00004E3E 663B03              <1> 	cmp	ax, [ebx]
  4869                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4870 00004E41 7433                <1> 	je	short anyi_3
  4871                              <1> 		; beq 1f / yes, 1f
  4872 00004E43 66F7D8              <1> 	neg	ax
  4873                              <1> 		; neg r1 / no complement r1
  4874 00004E46 663B03              <1> 	cmp	ax, [ebx]
  4875                              <1> 		; cmp r1,(r2) / do they match now?
  4876 00004E49 742B                <1> 	je	short anyi_3
  4877                              <1> 		; beq 1f / yes, transfer
  4878                              <1> 		; / i-numbers do not match
  4879 00004E4B 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4880                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4881                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4882 00004E4E 81FB[0C6F0000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4883                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4884                              <1> 				; / are we at last entry in the table
  4885 00004E54 72E8                <1> 	jb	short anyi_1
  4886                              <1> 		; blt 1b / no, check next entries i-number
  4887                              <1> 	;cmp	ax, 32768
  4888 00004E56 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4889                              <1> 		; tst r1 / yes, no match
  4890                              <1> 		; bge .+4
  4891 00004E59 7203                <1> 	jb	short anyi_2
  4892 00004E5B 66F7D8              <1> 	neg	ax
  4893                              <1> 		; neg r1 / make i-number positive
  4894                              <1> anyi_2:	
  4895 00004E5E E81A050000          <1> 	call	imap
  4896                              <1> 		; jsr r0,imap / get address of allocation bit 
  4897                              <1> 			    ; / in the i-map in r2
  4898                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4899                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4900                              <1>  	; not	dx
  4901 00004E63 F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4902                              <1>         ;and	[ebx], dx
  4903 00004E65 2013                <1> 	and 	[ebx], dl 
  4904                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4905 00004E67 E8A4040000          <1> 	call	itrunc
  4906                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4907 00004E6C 66C705[486C0000]00- <1>  	mov 	word [i.flgs], 0
  4907 00004E74 00                  <1>
  4908                              <1> 		; clr i.flgs / clear all flags in the i-node
  4909 00004E75 C3                  <1> 	retn
  4910                              <1> 		;rts	r0 / return
  4911                              <1> anyi_3: ; 1: / i-numbers match
  4912 00004E76 FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4913                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4914                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4915 00004E79 C3                  <1> 	retn
  4916                              <1> 		; rts r0
  2102                                  %include 'u3.s'        ; 10/05/2015
  2103                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS3.INC
  2104                              <1> ; Last Modification: 24/12/2021
  2105                              <1> ; ----------------------------------------------------------------------------
  2106                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2107                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2108                              <1> ;
  2109                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2110                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2111                              <1> ; <Bell Laboratories (17/3/1972)>
  2112                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2113                              <1> ;
  2114                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2115                              <1> ;
  2116                              <1> ; ****************************************************************************
  2117                              <1> 
  2118                              <1> tswitch: ; Retro UNIX 386 v1
  2119                              <1> tswap:
  2120                              <1> 	; 01/09/2015
  2121                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2122                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2123                              <1> 	; time out swap, called when a user times out.
  2124                              <1> 	; the user is put on the low priority queue.
  2125                              <1> 	; This is done by making a link from the last user
  2126                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2127                              <1> 	; then he is swapped out.
  2128                              <1> 	;
  2129                              <1> 	; Retro UNIX 386 v1 modification ->
  2130                              <1> 	;       swap (software task switch) is performed by changing
  2131                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2132                              <1> 	;	as in Retro UNIX 8086 v1.
  2133                              <1> 	;
  2134                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2135                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2136                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2137                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2138                              <1> 	;	compatibles was using 1MB segmented memory 
  2139                              <1> 	;	in 8086/8088 times.
  2140                              <1> 	;
  2141                              <1> 	; INPUTS ->
  2142                              <1> 	;    u.uno - users process number
  2143                              <1> 	;    runq+4 - lowest priority queue
  2144                              <1> 	; OUTPUTS ->
  2145                              <1> 	;    r0 - users process number
  2146                              <1> 	;    r2 - lowest priority queue address
  2147                              <1> 	;
  2148                              <1> 	; ((AX = R0, BX = R2)) output
  2149                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2150                              <1> 	;
  2151 00004E7A A0[9B6F0000]        <1> 	mov 	al, [u.uno]
  2152                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2153                              <1> 		; mov  $runq+4,r2 
  2154                              <1> 			; / move lowest priority queue address to r2
  2155 00004E7F E8CD000000          <1>         call 	putlu
  2156                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2157                              <1> 		             ; / u.uno's user
  2158                              <1> 
  2159                              <1> switch: ; Retro UNIX 386 v1
  2160                              <1> swap:
  2161                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2162                              <1> 	; 02/09/2015
  2163                              <1> 	; 01/09/2015
  2164                              <1> 	; 31/08/2015
  2165                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2166                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2167                              <1> 	; 'swap' is routine that controls the swapping of processes
  2168                              <1> 	; in and out of core.
  2169                              <1> 	;
  2170                              <1> 	; Retro UNIX 386 v1 modification ->
  2171                              <1> 	;       swap (software task switch) is performed by changing
  2172                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2173                              <1> 	;	as in Retro UNIX 8086 v1.
  2174                              <1> 	;
  2175                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2176                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2177                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2178                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2179                              <1> 	;	compatibles was using 1MB segmented memory 
  2180                              <1> 	;	in 8086/8088 times.
  2181                              <1> 	;
  2182                              <1> 	; INPUTS ->
  2183                              <1> 	;    runq table - contains processes to run.
  2184                              <1> 	;    p.link - contains next process in line to be run.
  2185                              <1> 	;    u.uno - process number of process in core	
  2186                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2187                              <1> 	; OUTPUTS ->
  2188                              <1> 	;    (original unix v1 -> present process to its disk block)
  2189                              <1> 	;    (original unix v1 -> new process into core -> 
  2190                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2191                              <1> 	;	   for new process)
  2192                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2193                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2194                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2195                              <1> 	;	 for now, it will swap the process if there is not
  2196                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2197                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2198                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2199                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2200                              <1> 	;
  2201                              <1> 	;    u.pri -points to highest priority run Q.
  2202                              <1> 	;    r2 - points to the run queue.
  2203                              <1> 	;    r1 - contains new process number
  2204                              <1> 	;    r0 - points to place in routine or process that called
  2205                              <1> 	;	  swap all user parameters
  2206                              <1> 	;				
  2207                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2208                              <1> 	;
  2209                              <1> swap_0:
  2210                              <1> 		;mov $300,*$ps / processor priority = 6
  2211 00004E84 BE[3C6F0000]        <1> 	mov	esi, runq
  2212                              <1> 		; mov $runq,r2 / r2 points to runq table
  2213                              <1> swap_1: ; 1: / search runq table for highest priority process
  2214 00004E89 668B06              <1> 	mov	ax, [esi]
  2215 00004E8C 6621C0              <1> 	and 	ax, ax
  2216                              <1>        		; tst (r2)+ / are there any processes to run 
  2217                              <1> 			  ; / in this Q entry
  2218 00004E8F 7507                <1> 	jnz	short swap_2
  2219                              <1>        		; bne 1f / yes, process 1f
  2220                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2221                              <1> 			       ; / to end of table
  2222                              <1> 		; bne 1b / if not at end, go back
  2223 00004E91 E8E0000000          <1> 	call	idle
  2224                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2225                              <1> 				       ; / all queues are empty
  2226 00004E96 EBF1                <1> 	jmp	short swap_1
  2227                              <1> 		; br swap
  2228                              <1> swap_2: ; 1:
  2229 00004E98 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2230                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2231                              <1>  		; mov r2,u.pri / set present user to this run queue
  2232                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2233 00004E9B 38E0                <1> 	cmp	al, ah
  2234                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2235                              <1> 			      ; / in this Q to be run
  2236 00004E9D 740A                <1> 	je	short swap_3
  2237                              <1>        		; beq 1f / yes
  2238                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2239                              <1> 	;movzx	ebx, al
  2240 00004E9F 8AA3[B76C0000]      <1> 	mov	ah, [ebx+p.link-1] 
  2241 00004EA5 8826                <1>        	mov	[esi], ah
  2242                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2243                              <1> 				       ; / in line into run queue
  2244 00004EA7 EB05                <1> 	jmp	short swap_4
  2245                              <1>        		; br 2f
  2246                              <1> swap_3: ; 1:
  2247                              <1> 	;xor	dx, dx
  2248                              <1> 	; 24/12/2021
  2249 00004EA9 31D2                <1> 	xor	edx, edx
  2250 00004EAB 668916              <1> 	mov	[esi], dx
  2251                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2252                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2253                              <1>       ; / in new process if required
  2254                              <1>        		; clr *$ps / clear processor status
  2255 00004EAE 8A25[9B6F0000]      <1> 	mov 	ah, [u.uno]
  2256 00004EB4 38C4                <1> 	cmp	ah, al
  2257                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2258                              <1> 			      ; / the process in core?
  2259 00004EB6 743B                <1>        	je	short swap_8
  2260                              <1>        		; beq 2f / yes, don't have to swap
  2261                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2262                              <1> 			   ; / (address in routine that called swap)
  2263                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2264                              <1> 	; 01/09/2015
  2265                              <1> 	;mov	[u.usp], esp
  2266                              <1>        		; mov sp,u.usp / save stack pointer
  2267                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2268                              <1> 			       ; / to the stack pointer
  2269 00004EB8 08E4                <1> 	or	ah, ah
  2270                              <1>        		; tstb u.uno / is the process # = 0
  2271 00004EBA 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2272                              <1> 		; beq 1f / yes, kill process by overwriting
  2273                              <1> 	; 02/09/2015
  2274 00004EBC 8925[486F0000]      <1> 	mov	[u.usp], esp ; return address for 'syswait' & 'sleep'
  2275                              <1> 	;
  2276 00004EC2 E834000000          <1> 	call	wswap
  2277                              <1> 		; jsr r0,wswap / write out core to disk
  2278                              <1> 	 ; 31/08/2015
  2279                              <1> 	;movzx	ebx, al ; New (running) process number
  2280 00004EC7 EB1C                <1> 	jmp 	short swap_7
  2281                              <1> swap_6:
  2282                              <1> 	; 31/08/2015
  2283                              <1> 	; Deallocate memory pages belong to the process
  2284                              <1> 	; which is being terminated
  2285                              <1> 	; 14/05/2015 ('sysexit')
  2286                              <1>  	; Deallocate memory pages of the process
  2287                              <1> 	; (Retro UNIX 386 v1 modification !)
  2288                              <1> 	;
  2289                              <1> 	; movzx ebx, al
  2290 00004EC9 53                  <1> 	push	ebx
  2291 00004ECA A1[A56F0000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2292 00004ECF 8B1D[A96F0000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2293 00004ED5 E80CE0FFFF          <1> 	call	deallocate_page_dir
  2294 00004EDA A1[9C6F0000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2295 00004EDF E89AE0FFFF          <1> 	call	deallocate_page
  2296 00004EE4 5B                  <1> 	pop	ebx
  2297                              <1> swap_7: ;1: 
  2298                              <1> 	; 02/09/2015
  2299                              <1> 	; 31/08/2015
  2300                              <1> 	; 14/05/2015
  2301 00004EE5 C0E302              <1> 	shl	bl, 2 ; * 4 
  2302 00004EE8 8B83[D46C0000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2303                              <1> 	;cli
  2304 00004EEE E831000000          <1> 	call	rswap
  2305                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2306                              <1> 		; jsr r0,rswap / read new process into core
  2307                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2308                              <1> 			      ; / to his program to its normal
  2309                              <1> 	; 01/09/2015
  2310                              <1> 	;mov	esp, [u.usp]	
  2311                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2312                              <1> 			     ; / new process stack
  2313                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2314                              <1> 			     ; / that just got swapped in, left off.,
  2315                              <1> 			     ; / i.e., transfer control to new process
  2316                              <1> 	;sti
  2317                              <1> swap_8: ;2:
  2318                              <1> 	; RETRO UNIX 8086 v1 modification !
  2319 00004EF3 C605[8E6F0000]04    <1> 	mov	byte [u.quant], time_count 
  2320                              <1> 		; movb $30.,uquant / initialize process time quantum
  2321 00004EFA C3                  <1> 	retn
  2322                              <1> 		; rts r0 / return
  2323                              <1> 
  2324                              <1> wswap:  ; < swap out, swap to disk >
  2325                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2326                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2327                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2328                              <1> 	; appropriate disk area.
  2329                              <1> 	;
  2330                              <1> 	; Retro UNIX 386 v1 modification ->
  2331                              <1> 	;       User (u) structure content and the user's register content
  2332                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2333                              <1> 	;	saving 'u' structure and user registers for task switching).
  2334                              <1> 	;	u.usp - points to kernel stack address which contains
  2335                              <1> 	;		user's registers while entering system call.  
  2336                              <1> 	;	u.sp  - points to kernel stack address 
  2337                              <1> 	;		to return from system call -for IRET-.
  2338                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2339                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2340                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2341                              <1> 	;
  2342                              <1> 	; Retro UNIX 8086 v1 modification ->
  2343                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2344                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2345                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2346                              <1> 	;	compatibles was using 1MB segmented memory 
  2347                              <1> 	;	in 8086/8088 times.
  2348                              <1> 	;
  2349                              <1> 	; INPUTS ->
  2350                              <1> 	;    u.break - points to end of program
  2351                              <1> 	;    u.usp - stack pointer at the moment of swap
  2352                              <1> 	;    core - beginning of process program		
  2353                              <1> 	;    ecore - end of core 	
  2354                              <1> 	;    user - start of user parameter area		
  2355                              <1> 	;    u.uno - user process number	
  2356                              <1> 	;    p.dska - holds block number of process	
  2357                              <1> 	; OUTPUTS ->
  2358                              <1> 	;    swp I/O queue
  2359                              <1> 	;    p.break - negative word count of process 
  2360                              <1> 	;    r1 - process disk address	
  2361                              <1> 	;    r2 - negative word count
  2362                              <1> 	;
  2363                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2364                              <1> 	;
  2365                              <1> 	; INPUTS ->
  2366                              <1> 	;    u.uno - process number (to be swapped out)
  2367                              <1> 	; OUTPUTS ->
  2368                              <1> 	;    none
  2369                              <1> 	;
  2370                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2371                              <1> 	;
  2372 00004EFB 8B3D[9C6F0000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2373 00004F01 B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2374 00004F06 BE[446F0000]        <1> 	mov	esi, user ; active user (u) structure	
  2375 00004F0B F3A5                <1> 	rep	movsd
  2376                              <1> 	;
  2377 00004F0D 8B35[486F0000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2378                              <1> 			     ;      points to user registers)
  2379 00004F13 8B0D[446F0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2380                              <1> 			     ; (for IRET)
  2381                              <1> 			     ; [u.sp] -> EIP (user)
  2382                              <1> 			     ; [u.sp+4]-> CS (user)
  2383                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2384                              <1> 			     ; [u.sp+12] -> ESP (user)
  2385                              <1> 			     ; [u.sp+16] -> SS (user)	
  2386 00004F19 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2387 00004F1B 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2388                              <1> 			     ; (for IRET) 	
  2389 00004F1E C1E902              <1> 	shr	ecx, 2	     		
  2390 00004F21 F3A5                <1> 	rep	movsd
  2391 00004F23 C3                  <1> 	retn
  2392                              <1> 
  2393                              <1> 	; Original UNIX v1 'wswap' routine:
  2394                              <1> 	; wswap:
  2395                              <1> 		; mov *$30,u.emt / determines handling of emts
  2396                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2397                              <1> 				; / illegal instructions
  2398                              <1> 		; mov u.break,r2 / put process program break address in r2
  2399                              <1> 		; inc r2 / add 1 to it 
  2400                              <1> 		; bic $1,r2 / make it even
  2401                              <1> 		; mov r2,u.break / set break to an even location
  2402                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2403                              <1> 			     ; / at moment of swap in r3
  2404                              <1> 		; cmp r2,$core / is u.break less than $core
  2405                              <1> 		; blos 2f / yes
  2406                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2407                              <1>        		; bhis 2f / yes
  2408                              <1> 	; 1:
  2409                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2410                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2411                              <1> 		; bne 1b / no, keep packing
  2412                              <1> 	 	; br 1f / yes
  2413                              <1> 	; 2:
  2414                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2415                              <1> 	; 1:
  2416                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2417                              <1> 			   ; / (user up to end of stack gets written out)
  2418                              <1> 		; neg r2 / make it negative
  2419                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2420                              <1> 		; mov r2,swp+4 / word count
  2421                              <1> 		; movb u.uno,r1 / move user process number to r1
  2422                              <1> 		; asl r1 / x2 for index
  2423                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2424                              <1> 				     ; / into the p.break table
  2425                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2426                              <1> 				    ; /	for process to r1
  2427                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2428                              <1> 			     ; / (block number)
  2429                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2430                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2431                              <1> 	; 1:
  2432                              <1>        		; tstb swp+1 / is lt done writing?
  2433                              <1>        		; bne 1b / no, wait
  2434                              <1> 		; rts r0 / yes, return to swap
  2435                              <1> 
  2436                              <1> rswap:  ; < swap in, swap from disk >
  2437                              <1> 	; 15/09/2015
  2438                              <1> 	; 28/08/2015
  2439                              <1> 	; 14/05/2015
  2440                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2441                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2442                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2443                              <1> 	; from disk into core.
  2444                              <1> 	;
  2445                              <1> 	; Retro UNIX 386 v1 modification ->
  2446                              <1> 	;       User (u) structure content and the user's register content
  2447                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2448                              <1> 	;	saving 'u' structure and user registers for task switching).
  2449                              <1> 	;	u.usp - points to kernel stack address which contains
  2450                              <1> 	;		user's registers while entering system call.  
  2451                              <1> 	;	u.sp  - points to kernel stack address 
  2452                              <1> 	;		to return from system call -for IRET-.
  2453                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2454                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2455                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2456                              <1> 	;
  2457                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2458                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2459                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2460                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2461                              <1> 	;	compatibles was using 1MB segmented memory 
  2462                              <1> 	;	in 8086/8088 times.
  2463                              <1> 	;
  2464                              <1> 	; INPUTS ->
  2465                              <1> 	;    r1 - process number of process to be read in
  2466                              <1> 	;    p.break - negative of word count of process 
  2467                              <1> 	;    p.dska - disk address of the process		
  2468                              <1> 	;    u.emt - determines handling of emt's 	
  2469                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2470                              <1> 	; OUTPUTS ->
  2471                              <1> 	;    8 = (u.ilgins)
  2472                              <1> 	;    24 = (u.emt)
  2473                              <1> 	;    swp - bit 10 is set to indicate read 
  2474                              <1> 	;		(bit 15=0 when reading is done)	
  2475                              <1> 	;    swp+2 - disk block address
  2476                              <1> 	;    swp+4 - negative word count 	
  2477                              <1> 	;      ((swp+6 - address of user structure)) 
  2478                              <1> 	;
  2479                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2480                              <1> 	;
  2481                              <1> 	; INPUTS ->
  2482                              <1> 	;    AL	- new process number (to be swapped in)	 
  2483                              <1> 	; OUTPUTS ->
  2484                              <1> 	;    none
  2485                              <1> 	;
  2486                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2487                              <1> 	;
  2488                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2489 00004F24 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2490 00004F26 B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2491 00004F2B BF[446F0000]        <1> 	mov	edi, user ; active user (u) structure	
  2492 00004F30 F3A5                <1> 	rep	movsd
  2493 00004F32 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2494 00004F33 8B3D[486F0000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2495                              <1> 			     ;      points to user registers)
  2496 00004F39 8B0D[446F0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2497                              <1> 			     ; (for IRET)
  2498                              <1> 			     ; [u.sp] -> EIP (user)
  2499                              <1> 			     ; [u.sp+4]-> CS (user)
  2500                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2501                              <1> 			     ; [u.sp+12] -> ESP (user)
  2502                              <1> 			     ; [u.sp+16] -> SS (user)		
  2503                              <1> 	; 28/08/2015
  2504 00004F3F 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2505 00004F41 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2506                              <1> 			     ; (for IRET) 	
  2507 00004F44 C1E902              <1> 	shr	ecx, 2	       		
  2508 00004F47 F3A5                <1> 	rep	movsd
  2509 00004F49 8B25[486F0000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2510 00004F4F 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2511 00004F50 C3                  <1> 	retn
  2512                              <1> 
  2513                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2514                              <1> 	;rswap:
  2515                              <1>        		; asl r1 / process number x2 for index
  2516                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2517                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2518                              <1>        		; bis $2000,swp / read
  2519                              <1>        		; jsr r0,ppoke / read it in 
  2520                              <1> 	; 1:
  2521                              <1>        		; tstb swp+1 / done
  2522                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2523                              <1>        		; mov u.emt,*$30 / yes move these
  2524                              <1>        		; mov u.ilgins,*$10 / back
  2525                              <1>        		; rts r0 / return
  2526                              <1> 
  2527                              <1> 	;unpack: ; / move stack back to its normal place
  2528                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2529                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2530                              <1> 		; blos 2f / yes, return
  2531                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2532                              <1> 			     ; / before swapping
  2533                              <1> 		; bhis 2f / yes, return
  2534                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2535                              <1> 		; add r3,r2
  2536                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2537                              <1> 	; 1:
  2538                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2539                              <1> 		; cmp r2,u.break / in core
  2540                              <1> 		; bne 1b
  2541                              <1> 	; 2:
  2542                              <1>        		; rts r0
  2543                              <1> 
  2544                              <1> putlu: 
  2545                              <1> 	; 12/09/2015
  2546                              <1> 	; 02/09/2015
  2547                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2548                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2549                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2550                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2551                              <1> 	; the last process on the queue to process in r1 by putting
  2552                              <1> 	; the process number in r1 into the last process's link.
  2553                              <1> 	;
  2554                              <1> 	; INPUTS ->
  2555                              <1> 	;    r1 - user process number
  2556                              <1> 	;    r2 - points to lowest priority queue 
  2557                              <1> 	;    p.dska - disk address of the process		
  2558                              <1> 	;    u.emt - determines handling of emt's 	
  2559                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2560                              <1> 	; OUTPUTS ->
  2561                              <1> 	;    r3 - process number of last process on the queue upon
  2562                              <1> 	;	  entering putlu
  2563                              <1> 	;    p.link-1 + r3 - process number in r1
  2564                              <1> 	;    r2 - points to lowest priority queue
  2565                              <1> 	;
  2566                              <1> 	; ((Modified registers: EDX, EBX)) 
  2567                              <1> 	;
  2568                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2569                              <1> 
  2570                              <1> 	; eBX = r2
  2571                              <1> 	; eAX = r1 (AL=r1b)
  2572                              <1> 
  2573 00004F51 BB[3C6F0000]        <1> 	mov	ebx, runq
  2574 00004F56 0FB613              <1> 	movzx  	edx, byte [ebx]
  2575 00004F59 43                  <1> 	inc	ebx
  2576 00004F5A 20D2                <1> 	and	dl, dl
  2577                              <1> 		; tstb (r2)+ / is queue empty?
  2578 00004F5C 740A                <1>        	jz	short putlu_1
  2579                              <1> 		; beq 1f / yes, branch
  2580 00004F5E 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2581                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2582                              <1> 			     ; / in r3
  2583 00004F60 8882[B76C0000]      <1>        	mov	[edx+p.link-1], al
  2584                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2585                              <1> 			     ; / "last users" link
  2586 00004F66 EB03                <1> 	jmp	short putlu_2
  2587                              <1> 		; br 2f /
  2588                              <1> putlu_1: ; 1:
  2589 00004F68 8843FF              <1> 	mov	[ebx-1], al
  2590                              <1>        		; movb r1,-1(r2) / user is only user; 
  2591                              <1> 			    ; / put process no. at beginning and at end
  2592                              <1> putlu_2: ; 2: 
  2593 00004F6B 8803                <1> 	mov	[ebx], al
  2594                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2595                              <1> 			     ; / on the queue
  2596 00004F6D 88C2                <1> 	mov	dl, al
  2597 00004F6F 88B2[B76C0000]      <1>         mov     [edx+p.link-1], dh ; 0
  2598                              <1> 		; dec r2 / restore r2
  2599 00004F75 C3                  <1>         retn
  2600                              <1> 		; rts r0
  2601                              <1> 
  2602                              <1> ;copyz:
  2603                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2604                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2605                              <1> ;       mov     (r0)+,r1
  2606                              <1> ;       mov     (r0)+,r2
  2607                              <1> ;1:
  2608                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2609                              <1> ;       cmp     r1,r2 
  2610                              <1> ;       blo     1b
  2611                              <1> ;       mov     (sp)+,r2 / restore r2
  2612                              <1> ;       mov     (sp)+,r1 / restore r1
  2613                              <1> ;       rts     r0 
  2614                              <1> 
  2615                              <1> idle:
  2616                              <1> 	; 01/09/2015
  2617                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2618                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2619                              <1> 	; (idle & wait loop)
  2620                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2621                              <1> 	; idle procedure!
  2622                              <1>       	;
  2623                              <1>   	; 01/09/2015
  2624 00004F76 FB                  <1> 	sti
  2625                              <1>       	; 29/07/2013
  2626 00004F77 F4                  <1>       	hlt
  2627 00004F78 90                  <1>       	nop ; 10/10/2013
  2628 00004F79 90                  <1>       	nop
  2629 00004F7A 90                  <1>       	nop
  2630                              <1>       	; 23/10/2013
  2631 00004F7B 90                  <1>       	nop
  2632 00004F7C 90                  <1>       	nop
  2633 00004F7D 90                  <1>       	nop
  2634 00004F7E 90                  <1>       	nop
  2635 00004F7F C3                  <1>       	retn      
  2636                              <1> 
  2637                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2638                              <1> 	;clr *$ps / clear ps
  2639                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2640                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2641                              <1> 	;1 / wait for interrupt
  2642                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2643                              <1> 	;mov (sp)+,*$ps
  2644                              <1> 	;rts r0
  2645                              <1> 
  2646                              <1> clear:
  2647                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2648                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2649                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2650                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2651                              <1> 	; on the current device (cdev)
  2652                              <1> 	;	
  2653                              <1> 	; INPUTS ->
  2654                              <1> 	;    r1 - block number of block to be zeroed
  2655                              <1> 	;    cdev - current device number 
  2656                              <1> 	; OUTPUTS ->
  2657                              <1> 	;    a zeroed I/O buffer onto the current device
  2658                              <1> 	;    r1 - points to last entry in the I/O buffer
  2659                              <1> 	;
  2660                              <1> 	; ((AX = R1)) input/output
  2661                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2662                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2663                              <1> 
  2664 00004F80 E80E0E0000          <1> 	call 	wslot
  2665                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2666                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2667 00004F85 89DF                <1> 	mov	edi, ebx ; r5
  2668 00004F87 89C2                <1> 	mov	edx, eax
  2669 00004F89 B980000000          <1> 	mov	ecx, 128
  2670                              <1> 		; mov $256.,r3
  2671 00004F8E 31C0                <1> 	xor	eax, eax
  2672 00004F90 F3AB                <1> 	rep	stosd
  2673 00004F92 89D0                <1> 	mov	eax, edx
  2674                              <1> ; 1: 
  2675                              <1>        		; clr (r5)+ / zero data word in buffer
  2676                              <1>        		; dec r3
  2677                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2678                              <1> 	;call	dskwr
  2679                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2680                              <1>                              ; / block specified in r1
  2681                              <1> 	; eAX (r1) = block number
  2682                              <1> 	;retn
  2683                              <1> 		; rts r0
  2684                              <1> 	; 24/12/2021
  2685 00004F94 E9160E0000          <1> 	jmp	dskwr
  2103                                  %include 'u4.s'        ; 15/04/2015
  2104                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS4.INC
  2105                              <1> ; Last Modification: 26/02/2022
  2106                              <1> ; ----------------------------------------------------------------------------
  2107                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2108                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2109                              <1> ;
  2110                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2111                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2112                              <1> ; <Bell Laboratories (17/3/1972)>
  2113                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2114                              <1> ;
  2115                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2116                              <1> ;
  2117                              <1> ; ****************************************************************************
  2118                              <1> 
  2119                              <1> ;setisp:
  2120                              <1>        ;mov     r1,-(sp)
  2121                              <1>        ;mov     r2,-(sp)
  2122                              <1>        ;mov     r3,-(sp)
  2123                              <1>        ;mov     clockp,-(sp)
  2124                              <1>        ;mov     $s.syst+2,clockp
  2125                              <1>        ;jmp     (r0)
  2126                              <1> 
  2127                              <1> clock: ; / interrupt from 60 cycle clock
  2128                              <1> 	
  2129                              <1> 	; 14/10/2015
  2130                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2131                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2132                              <1> 
  2133                              <1>        ;mov     r0,-(sp) / save r0
  2134                              <1>        ;tst     *$lks / restart clock?
  2135                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2136                              <1>        ;inc     (r0)
  2137                              <1>        ;bne     1f
  2138                              <1>        ;inc     -(r0)
  2139                              <1> ;1:
  2140                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2141                              <1>        ;inc     (r0)
  2142                              <1>        ;bne     1f
  2143                              <1>        ;inc     -(r0)
  2144                              <1> ;1:
  2145                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2146                              <1> 
  2147 00004F99 803D[8E6F0000]00    <1> 	cmp	byte [u.quant], 0
  2148 00004FA0 772C                <1> 	ja	short clk_1
  2149                              <1> 	;
  2150 00004FA2 803D[416F0000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2151 00004FA9 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2152 00004FAB 803D[9B6F0000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2153 00004FB2 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2154 00004FB4 66833D[906F0000]00  <1> 	cmp	word [u.intr], 0
  2155 00004FBC 7616                <1> 	jna	short clk_2
  2156                              <1> clk_0:
  2157                              <1> 	; 14/10/2015
  2158 00004FBE FE05[416F0000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2159 00004FC4 58                  <1> 	pop	eax ; return address to the timer interrupt
  2160                              <1> 	;
  2161 00004FC5 B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2162                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2163 00004FC7 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2164                              <1> 	;
  2165 00004FC9 E97EEBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2166                              <1> clk_1:
  2167 00004FCE FE0D[8E6F0000]      <1> 	dec	byte [u.quant]
  2168                              <1> clk_2:
  2169 00004FD4 C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2170                              <1> 
  2171                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2172                              <1> 
  2173                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2174                              <1>        ;decb    (r0)
  2175                              <1>        ;bge     1f / if less than 0
  2176                              <1>        ;clrb    (r0) / make it 0
  2177                              <1> ;1: / decrement time out counts return now if priority was not 0
  2178                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2179                              <1>        ;bge     2f / yes, check time outs
  2180                              <1>        ;tstb    (r0) / no, user timed out?
  2181                              <1>        ;bne     1f / no
  2182                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2183                              <1>        ;bne     1f / no, 1f
  2184                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2185                              <1>        ;sys     0 / sysrele
  2186                              <1>        ;rti
  2187                              <1> ;2: / priority is high so just decrement time out counts
  2188                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2189                              <1> ;2:
  2190                              <1>        ;tstb    (r0) / is the time out?
  2191                              <1>        ;beq     3f / yes, 3f (get next entry)
  2192                              <1>        ;decb    (r0) / no, decrement the time
  2193                              <1>        ;bne     3f / isit zero now?
  2194                              <1>        ;incb    (r0) / yes, increment the time
  2195                              <1> ;3:
  2196                              <1>        ;inc     r0 / next entry
  2197                              <1>        ;cmp     r0,$touts / end of toutt table?
  2198                              <1>        ;blo     2b / no, check this entry
  2199                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2200                              <1>        ;rti / return from interrupt
  2201                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2202                              <1>        ;mov     (sp)+,r0 / restore r0
  2203                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2204                              <1>        ;jsr     r0,setisp / save registers
  2205                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2206                              <1>                                ;  / the table
  2207                              <1> ;1:
  2208                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2209                              <1>        ;beq     2f / yes
  2210                              <1>        ;decb    toutt(r0) / no, decrement the time
  2211                              <1>        ;bne     2f / is the time 0, now
  2212                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2213                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2214                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2215                              <1> ;2:
  2216                              <1>        ;dec     r0 / set up r0 for next entry
  2217                              <1>        ;bge     1b / finished? , no, go back
  2218                              <1>        ;br      retisp / yes, restore registers and do a rti
  2219                              <1> 
  2220                              <1> ;retisp:
  2221                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2222                              <1>        ;mov     (sp)+,r3
  2223                              <1>        ;mov     (sp)+,r2
  2224                              <1>        ;mov     (sp)+,r1
  2225                              <1>        ;mov     (sp)+,r0
  2226                              <1>        ;rti     / return from interrupt
  2227                              <1> 
  2228                              <1> 
  2229                              <1> wakeup: ; / wakeup processes waiting for an event 
  2230                              <1> 	; / by linking them to the queue
  2231                              <1> 	;
  2232                              <1> 	; 26/02/2022
  2233                              <1> 	; 15/09/2015
  2234                              <1> 	; 29/06/2015
  2235                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2236                              <1> 	;
  2237                              <1> 	; 15/05/2013 - 02/06/2014
  2238                              <1> 	; Retro UNIX 8086 v1 modification !
  2239                              <1> 	; (Process/task switching routine by using
  2240                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2241                              <1> 	;
  2242                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2243                              <1> 	; sleeping in the specified wait channel by creating a link 
  2244                              <1> 	; to it from the last user process on the run queue.
  2245                              <1> 	; If there is no process to wake up, nothing happens.
  2246                              <1> 	;
  2247                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2248                              <1> 	; 'switching' status of the current process (owns current tty)
  2249                              <1> 	; (via alt + function keys) to a process which has highest
  2250                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2251                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2252                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2253                              <1> 	; tty for tty switching by keyboard.)	 
  2254                              <1> 	; 
  2255                              <1> 	; INPUT -> 
  2256                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2257                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2258                              <1> 	;
  2259                              <1> 	; ((modified registers: EAX, EBX))
  2260                              <1> 	;
  2261 00004FD5 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2262 00004FD8 81C3[E86B0000]      <1> 	add	ebx, wlist
  2263 00004FDE 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2264 00004FE0 20C0                <1> 	and	al, al
  2265 00004FE2 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2266                              <1> 	;
  2267 00004FE4 30E4                <1> 	xor	ah, ah
  2268 00004FE6 8825[8E6F0000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2269 00004FEC 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2270                              <1> 	; 15/09/2015
  2271 00004FEE 0FB6D8              <1> 	movzx	ebx, al
  2272                              <1> 	; 26/02/2022 (p.waitc is not used)
  2273                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2274 00004FF1 FEC4                <1> 	inc	ah
  2275 00004FF3 88A3[C76C0000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2276                              <1> 	;
  2277 00004FF9 57                  <1> 	push	edi
  2278 00004FFA 52                  <1> 	push	edx
  2279 00004FFB E851FFFFFF          <1> 	call	putlu
  2280 00005000 5A                  <1> 	pop	edx
  2281 00005001 5F                  <1> 	pop	edi
  2282                              <1> wa0:
  2283 00005002 C3                  <1> 	retn
  2284                              <1> 
  2285                              <1> sleep: 
  2286                              <1> 	; 26/02/2022
  2287                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2288                              <1> 	; 15/09/2015
  2289                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2290                              <1> 	;
  2291                              <1> 	; 09/05/2013 - 20/03/2014
  2292                              <1> 	;
  2293                              <1> 	; Retro UNIX 8086 v1 modification !
  2294                              <1> 	; (Process/task switching and quit routine by using
  2295                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2296                              <1> 	;
  2297                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2298                              <1> 	; tty and tape output or input becomes available
  2299                              <1> 	; and process is put on waiting channel and swapped out,
  2300                              <1> 	; then -when the tty or tape is ready to write or read-
  2301                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2302                              <1> 	;
  2303                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2304                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2305                              <1> 	; status of the current process also INT 1Ch will count down
  2306                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2307                              <1> 	; to tty buffer of the current process and kernel will get
  2308                              <1> 	; user input by using tty buffer of the current process
  2309                              <1> 	; (instead of standard INT 16h interrupt).
  2310                              <1> 	; TTY output will be redirected to related video page of text mode
  2311                              <1> 	; (INT 10h will be called with different video page depending
  2312                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2313                              <1> 	; pseudo screens.)
  2314                              <1> 	;
  2315                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2316                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2317                              <1> 	; characters/data on serial port(s).
  2318                              <1> 	;
  2319                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2320                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2321                              <1> 	; 
  2322                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2323                              <1> 	;
  2324                              <1> 	;; 05/10/2013
  2325                              <1>         ;10/12/2013
  2326                              <1> 	;cmp   byte [u.uno], 1
  2327                              <1>         ;ja    short sleep0
  2328                              <1> 	;retn
  2329                              <1> 
  2330                              <1> 	; 20/03/2014
  2331                              <1> 	;mov	bx, [runq]
  2332                              <1> 	;cmp	bl, bh
  2333                              <1> 	;jne	short sleep0	
  2334                              <1> 	; 25/02/2014
  2335                              <1> 	;cmp word ptr [runq], 0
  2336                              <1> 	;ja short sleep0	
  2337                              <1> 	;retn
  2338                              <1> sleep0:
  2339                              <1> 	;
  2340 00005003 E849000000          <1> 	call	isintr
  2341                              <1> 	;jnz	sysret
  2342                              <1> 		; / wait for event
  2343                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2344                              <1> 			      ; / or quit from user
  2345                              <1>                		; br 2f / something happened
  2346                              <1> 			      ; / yes, his interrupt so return
  2347                              <1>                      	      ;	/ to user
  2348                              <1> 	; 24/12/2021
  2349 00005008 7405                <1> 	jz	short sleep_2
  2350                              <1> sleep_3:
  2351 0000500A E9D8EAFFFF          <1> 	jmp	sysret
  2352                              <1> sleep_2:
  2353                              <1> 	; 30/06/2015
  2354 0000500F 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2355 00005012 81C3[E86B0000]      <1> 	add	ebx, wlist
  2356 00005018 8A03                <1> 	mov	al, [ebx]
  2357 0000501A 20C0                <1> 	and	al, al
  2358 0000501C 7407                <1> 	jz	short sleep1
  2359 0000501E 53                  <1> 	push	ebx
  2360 0000501F E82DFFFFFF          <1> 	call	putlu
  2361 00005024 5B                  <1> 	pop	ebx
  2362                              <1> sleep1:
  2363 00005025 A0[9B6F0000]        <1> 	mov	al, [u.uno]    
  2364 0000502A 8803                <1>   	mov	[ebx], al 	; put the process number
  2365                              <1> 				; in the wait channel
  2366                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2367                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2368                              <1> 				     ; / on the stack
  2369                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2370                              <1> 				     ; / to put to sleep in there
  2371                              <1>         ; 15/09/2015
  2372 0000502C 0FB6D8              <1> 	movzx	ebx, al
  2373 0000502F C683[C76C0000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2374                              <1> 	; 26/02/2022 (p.waitc is not used)
  2375                              <1> 	;inc	ah
  2376                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2377                              <1> 	;
  2378 00005036 66FF35[2F6F0000]    <1> 	push    word [cdev]
  2379                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2380 0000503D E842FEFFFF          <1> 	call	swap
  2381                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2382 00005042 668F05[2F6F0000]    <1>         pop     word [cdev]
  2383                              <1> 		; mov (sp)+,cdev / restore device
  2384 00005049 E803000000          <1> 	call	isintr
  2385                              <1> 	; 22/09/2013
  2386                              <1> 	;jnz	sysret         
  2387                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2388                              <1>                		; br 2f / yes, return to new user
  2389                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2390                              <1> 				; / originally on the wait channel
  2391                              <1>        		; beq 1f / if 0 branch
  2392                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2393                              <1>        		; mov $300,*$ps / processor priority = 6
  2394                              <1> 		; jsr r0,putlu / create link to old process number
  2395                              <1>        		; clr *$ps / clear the status; process priority = 0
  2396                              <1> 	; 24/12/2021
  2397 0000504E 75BA                <1> 	jnz	short sleep_3 ; jump to sysret
  2398                              <1>      ;1:
  2399 00005050 C3                  <1> 	retn
  2400                              <1> 		; rts r0 / return
  2401                              <1>      ;2:
  2402                              <1>         ;;jmp	sysret
  2403                              <1> 		; jmp sysret / return to user
  2404                              <1> 
  2405                              <1> isintr:
  2406                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2407                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2408                              <1> 	;
  2409                              <1> 	; 09/05/2013 - 30/05/2014
  2410                              <1> 	;
  2411                              <1> 	; Retro UNIX 8086 v1 modification !
  2412                              <1> 	; (Process/task switching and quit routine by using
  2413                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2414                              <1> 	;
  2415                              <1> 	; Retro UNIX 8086 v1 modification:
  2416                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2417                              <1> 	;  and there is a 'quit' request by user;
  2418                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2419                              <1> 	;  "nothing to do". (20/10/2013)
  2420                              <1> 	;
  2421                              <1> 	; 20/10/2013
  2422 00005051 66833D[7C6F0000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2423 00005059 761F                <1> 	jna	short isintr2 ; retn
  2424                              <1> 	; 03/09/2013
  2425                              <1> 	; (nothing to do)
  2426                              <1> 	;retn
  2427                              <1> 	; 22/09/2013
  2428 0000505B 66833D[906F0000]00  <1> 	cmp	word [u.intr], 0
  2429 00005063 7615                <1> 	jna	short isintr2 ; retn
  2430                              <1> 	; 30/05/2014
  2431                              <1> 	;push	ax
  2432                              <1> 	; 24/12/2021
  2433 00005065 50                  <1> 	push	eax
  2434 00005066 66A1[926F0000]      <1> 	mov	ax, [u.quit]
  2435 0000506C 6609C0              <1> 	or	ax, ax ; 0 ?
  2436 0000506F 7408                <1> 	jz	short isintr1 ; zf = 1
  2437 00005071 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2438 00005075 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2439                              <1> 	;xor	ax, ax ; zf = 1
  2440                              <1> 	; 24/12/2021
  2441 00005077 31C0                <1> 	xor	eax, eax ; zf = 1
  2442                              <1> isintr1:
  2443                              <1> 	;pop	ax
  2444                              <1> 	; 24/12/2021
  2445 00005079 58                  <1> 	pop	eax
  2446                              <1> isintr2: ; 22/09/2013
  2447                              <1> 	; zf=1 -> nothing to do
  2448 0000507A C3                  <1> 	retn
  2449                              <1> 
  2450                              <1> 	; UNIX v1 original 'isintr' routine... 
  2451                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2452                              <1>        	;mov     r2,-(sp) / save r2
  2453                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2454                              <1>         ;                 / typewriter
  2455                              <1>        	;beq     1f / if 0, do nothing except skip return
  2456                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2457                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2458                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2459                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2460                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2461                              <1>         ;              / of interrupts
  2462                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2463                              <1>      ;1:
  2464                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2465                              <1>      ;4:
  2466                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2467                              <1>        	;mov     (sp)+,r1
  2468                              <1>        	;rts     r0
  2469                              <1>      ;3: / interrupt char = quit (fs)
  2470                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2471                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2472                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2473                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2474                              <1>      ;1: / find process control tty entry in tty block
  2475                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2476                              <1>        	;beq     1f / block found go to 1f
  2477                              <1>        	;add     $8,r1 / look at next tty block
  2478                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2479                              <1>        	;blo     1b / no
  2480                              <1>        	;br      4b / no process control tty found so go to 4b
  2481                              <1>      ;1:
  2482                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2483                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2484                              <1>         ;                  / identifier
  2485                              <1>        	;inc     0f / increment
  2486                              <1>      ;1:
  2487                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2488                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2489                              <1>         ;             / being typed out after you hit the interrupt
  2490                              <1>         ;             / key
  2491                              <1>        	;br      1b
  2104                                  %include 'u5.s'        ; 03/06/2015
  2105                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS5.INC
  2106                              <1> ; Last Modification: 22/04/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 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2117                              <1> ;
  2118                              <1> ; ****************************************************************************
  2119                              <1> 
  2120                              <1> mget:
  2121                              <1> 	; 22/04/2022
  2122                              <1> 	; 09/01/2022
  2123                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2124                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2125                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2126                              <1> 	;
  2127                              <1> 	; Get existing or (allocate) a new disk block for file
  2128                              <1> 	; 
  2129                              <1> 	; INPUTS ->
  2130                              <1> 	;    u.fofp (file offset pointer)
  2131                              <1> 	;    inode 
  2132                              <1> 	;    u.off (file offset)
  2133                              <1> 	; OUTPUTS ->
  2134                              <1> 	;    r1 (physical block number)
  2135                              <1> 	;    r2, r3, r5 (internal)
  2136                              <1> 	;
  2137                              <1> 	; ((AX = R1)) output
  2138                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2139                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2140                              <1> 
  2141                              <1> 		; mov *u.fofp,mq / file offset in mq
  2142                              <1> 		; clr ac / later to be high sig
  2143                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2144                              <1> 		; mov mq,r2
  2145                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2146                              <1> 		; bne 4f / branch for large file
  2147                              <1> mget_0:	
  2148                              <1> 	; 09/01/2022
  2149 0000507B 29C0                <1> 	sub	eax, eax
  2150 0000507D 29D2                <1> 	sub	edx, edx
  2151 0000507F 29C9                <1> 	sub	ecx, ecx
  2152 00005081 29DB                <1> 	sub	ebx, ebx
  2153                              <1> 
  2154 00005083 8B35[5C6F0000]      <1>         mov     esi, [u.fofp]
  2155                              <1>         ;movzx	ebx, byte [esi+1]
  2156                              <1> 	; 09/01/2022
  2157 00005089 46                  <1> 	inc	esi
  2158 0000508A 8A1E                <1> 	mov	bl, [esi]
  2159                              <1> 
  2160                              <1> 	; BX = r2
  2161                              <1>         ; 24/12/2021
  2162 0000508C F605[496C0000]10    <1> 	test	byte [i.flgs+1], 10h
  2163                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2164                              <1> 				  ; is this a large or small file
  2165 00005093 756C                <1> 	jnz 	short mget_5 ; 4f ; large file
  2166                              <1> 
  2167 00005095 F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2168                              <1> 		; bit $!17,r2
  2169 00005098 7525                <1> 	jnz 	short mget_2
  2170                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2171 0000509A 80E30E              <1>         and     bl, 0Eh  
  2172                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2173                              <1> 	; 09/01/2021
  2174 0000509D 668B83[4E6C0000]    <1> 	mov	ax, [ebx+i.dskp]
  2175                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2176                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2177                              <1> 	; 24/12/2021
  2178 000050A4 09C0                <1> 	or	eax, eax
  2179                              <1> 	;or 	ax, ax
  2180 000050A6 7516                <1> 	jnz 	short mget_1 
  2181                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2182                              <1> 		       ; / for file
  2183 000050A8 E8A6000000          <1> 	call 	alloc
  2184                              <1> 		; jsr r0,alloc / allocate a new block
  2185                              <1>          ; eAX (r1) = Physical block number
  2186 000050AD 668983[4E6C0000]    <1> 	mov 	[ebx+i.dskp], ax
  2187                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2188 000050B4 E835020000          <1> 	call 	setimod	
  2189                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2190 000050B9 E8C2FEFFFF          <1> 	call	clear
  2191                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2192                              <1> mget_1: ; 2:
  2193                              <1>         ; eAX (r1) = Physical block number
  2194 000050BE C3                  <1> 	retn 
  2195                              <1> 		; rts r0
  2196                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2197 000050BF E88F000000          <1> 	call 	alloc
  2198                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2199                              <1> 	                     ; / block number in r1
  2200                              <1>         ; eAX (r1) = Physical block number
  2201 000050C4 E8CA0C0000          <1> 	call 	wslot
  2202                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2203                              <1> 			     ; / first data word in buffer
  2204                              <1>         ; eAX (r1) = Physical block number
  2205                              <1> 	; 09/01/2022
  2206 000050C9 31C9                <1> 	xor	ecx, ecx
  2207 000050CB B108                <1> 	mov	cl, 8
  2208                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2209                              <1> 		   ; into new indirect block area for the new
  2210                              <1> 		   ; large file		
  2211 000050CD 89DF                <1> 	mov 	edi, ebx ; r5
  2212 000050CF BE[4E6C0000]        <1> 	mov 	esi, i.dskp 
  2213                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2214                              <1> 			   ; / block pointers
  2215                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2216                              <1> 			  ; / large file
  2217                              <1> 	; 22/04/2022
  2218 000050D4 50                  <1> 	push	eax ; * ; bugfix
  2219                              <1> 
  2220                              <1> 	;xor 	ax, ax ; mov ax, 0
  2221                              <1> 	; 24/12/2021
  2222 000050D5 31C0                <1> 	xor	eax, eax
  2223                              <1> mget_3: ;1:
  2224 000050D7 66A5                <1> 	movsw
  2225                              <1> 		; mov (r2),(r5)+
  2226 000050D9 668946FE            <1> 	mov 	[esi-2], ax
  2227                              <1> 		; clr (r2)+
  2228 000050DD E2F8                <1> 	loop	mget_3 ; 1b
  2229                              <1> 		; dec r3
  2230                              <1> 		; bgt 1b
  2231                              <1> 
  2232 000050DF B1F8                <1> 	mov 	cl, 256-8
  2233                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2234                              <1> mget_4:	; 1
  2235 000050E1 F366AB              <1> 	rep 	stosw
  2236                              <1> 		; clr (r5)+
  2237                              <1> 		; dec r3
  2238                              <1> 		; bgt 1b
  2239                              <1> 
  2240                              <1> 	; 22/04/2022
  2241                              <1> 	;pop	eax ; * ; bugfix
  2242                              <1> 
  2243                              <1> 	; 24/03/2013
  2244                              <1>         ; AX (r1) = Physical block number
  2245 000050E4 E8C60C0000          <1> 	call	dskwr
  2246                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2247                              <1> 
  2248                              <1> 	; 22/04/2022
  2249 000050E9 58                  <1> 	pop	eax ; * ; bugfix
  2250                              <1> 
  2251                              <1>         ; eAX (r1) = Physical block number
  2252 000050EA 66A3[4E6C0000]      <1> 	mov 	[i.dskp], ax
  2253                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2254                              <1> 	; 09/01/2022
  2255 000050F0 800D[496C0000]10    <1> 	or	byte [i.flgs+1], 10h
  2256                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2257                              <1> 		; bis $10000,i.flgs / set large file bit 
  2258                              <1> 				  ; / in i.flgs word of i-node
  2259 000050F7 E8F2010000          <1> 	call	setimod
  2260                              <1> 		; jsr r0,setimod / set i-node modified flag
  2261 000050FC E97AFFFFFF          <1>         jmp     mget_0 
  2262                              <1> 		; br mget
  2263                              <1> 
  2264                              <1> mget_5:  ; 4 ; large file
  2265                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2266                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2267                              <1> 			    ; / in indirect block
  2268                              <1> 		; mov r2,-(sp) / save on stack (*)
  2269                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2270                              <1>        		          ; / indirect block
  2271                              <1> 		; bic $!16,r2
  2272 00005101 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2273 00005104 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2274                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2275                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2276                              <1> 	; There is always 1 indirect block for this file system
  2277                              <1> 	; 09/01/2022
  2278 00005105 66A1[4E6C0000]      <1> 	mov	ax, [i.dskp]
  2279                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2280                              <1> 		; mov i.dskp(r2),r1
  2281                              <1> 	; 09/01/2022
  2282 0000510B 09C0                <1> 	or	eax, eax
  2283                              <1> 	;or 	ax, ax ; R1
  2284 0000510D 7515                <1> 	jnz 	short mget_6 ; 2f
  2285                              <1> 		; bne 2f / if no indirect block exists
  2286 0000510F E83F000000          <1> 	call 	alloc
  2287                              <1> 		; jsr r0,alloc / allocate a new block
  2288 00005114 66A3[4E6C0000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2289                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2290 0000511A E8CF010000          <1> 	call 	setimod
  2291                              <1> 		; jsr r0,setimod / set i-node modified byte
  2292                              <1> 	; eAX = new block number
  2293 0000511F E85CFEFFFF          <1> 	call 	clear
  2294                              <1> 		; jsr r0,clear / clear new block
  2295                              <1> mget_6: ;2
  2296                              <1> 	; 05/03/2013
  2297                              <1> 	; eAX = r1, physical block number (of indirect block)
  2298 00005124 E8F80B0000          <1> 	call 	dskrd ; read indirect block
  2299                              <1> 		; jsr r0,dskrd / read in indirect block
  2300 00005129 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2301                              <1> 		; mov (sp)+,r2 / get offset
  2302                              <1> 	; eAX = r1, physical block number (of indirect block)
  2303 0000512A 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2304                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2305                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2306 0000512B 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2307                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2308                              <1> 	                  ; / points to location of inter
  2309                              <1> 	; 09/01/2022
  2310 0000512D 668B03              <1> 	mov	ax, [ebx]
  2311                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2312                              <1> 			      ; in file sought in R1 (AX)
  2313                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2314                              <1> 	               	    ; / sought in r1
  2315                              <1> 	; 09/01/2022
  2316 00005130 09C0                <1> 	or	eax, eax
  2317                              <1> 	;or 	ax, ax
  2318 00005132 751D                <1>         jnz 	short mget_7 ; 2f
  2319                              <1> 		; bne 2f / if no block exists 
  2320 00005134 E81A000000          <1> 	call 	alloc
  2321                              <1> 		; jsr r0,alloc / allocate a new block
  2322 00005139 668903              <1> 	mov 	[ebx], ax ; R1
  2323                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2324                              <1> 	                    ; / indirect block
  2325 0000513C 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2326                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2327 0000513D 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2328 0000513E 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2329 0000513F 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2330                              <1> 		; mov (r2),-(sp) / save block number of new block
  2331                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2332 00005141 E84D0C0000          <1> 	call 	wslot
  2333                              <1> 		; jsr r0,wslot
  2334                              <1>         ; eAX (r1) = physical block number
  2335                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2336 00005146 E8640C0000          <1> 	call 	dskwr
  2337                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2338                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2339                              <1> 			     ; / back out on disk
  2340 0000514B 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2341                              <1> 		; mov (sp),r1 / restore block number of new block	
  2342                              <1> 	; eAX (r1) = physical block number of new block
  2343 0000514C E82FFEFFFF          <1> 	call 	clear
  2344                              <1> 		; jsr r0,clear / clear new block	
  2345                              <1> mget_7: ; 2
  2346 00005151 5A                  <1> 	pop 	edx ; **
  2347                              <1> 		; tst (sp)+ / bump stack pointer
  2348                              <1> 	; eAX (r1) = Block number of new block
  2349 00005152 C3                  <1> 	retn
  2350                              <1> 		; rts r0
  2351                              <1> 
  2352                              <1> alloc:
  2353                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2354                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2355                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2356                              <1> 	;
  2357                              <1> 	; get a free block and 
  2358                              <1> 	; set the corresponding bit in the free storage map
  2359                              <1> 	; 
  2360                              <1> 	; INPUTS ->
  2361                              <1> 	;    cdev (current device)
  2362                              <1> 	;    r2 
  2363                              <1> 	;    r3
  2364                              <1> 	; OUTPUTS ->
  2365                              <1> 	;    r1 (physical block number of block assigned)
  2366                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2367                              <1> 	;
  2368                              <1> 	; ((AX = R1)) output
  2369                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2370                              <1>         ;    ((Modified registers: DX, CX))  
  2371                              <1> 
  2372                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2373                              <1> 		;mov r3,-(sp)
  2374                              <1> 	;push 	ecx
  2375 00005153 53                  <1> 	push 	ebx ; R2
  2376                              <1> 	;push 	edx ; R3
  2377 00005154 BB[0C7C0000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2378                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2379 00005159 803D[2F6F0000]00    <1> 	cmp 	byte [cdev], 0
  2380                              <1> 		; tst cdev
  2381 00005160 7605                <1> 	jna	short alloc_1
  2382                              <1> 		; beq 1f / drum is device
  2383 00005162 BB[147E0000]        <1> 	mov	ebx, mount
  2384                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2385                              <1> 			      ; / free storage map
  2386                              <1> alloc_1: ; 1
  2387                              <1> 	; 09/01/2022
  2388                              <1> 	;sub	ecx, ecx
  2389                              <1> 	;sub	edx, edx
  2390                              <1> 	;sub	eax, eax
  2391                              <1> 
  2392 00005167 668B0B              <1>         mov	cx, [ebx]
  2393                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2394                              <1> 			     ; / storage map
  2395                              <1> 	; 09/01/2022
  2396 0000516A C1E103              <1> 	shl	ecx, 3
  2397                              <1> 	;shl	cx, 3
  2398                              <1> 		; asl r1 / multiply r1 by eight gives 
  2399                              <1> 		; number of blocks in device
  2400                              <1> 		; asl r1
  2401                              <1> 		; asl r1
  2402                              <1> 	;;push	cx ;; 01/08/2013
  2403                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2404 0000516D 31C0                <1> 	xor 	eax, eax ; 0
  2405                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2406                              <1> alloc_2: ; 1
  2407 0000516F 43                  <1> 	inc 	ebx ; 18/8/2012
  2408 00005170 43                  <1> 	inc 	ebx ; 
  2409 00005171 668B13              <1> 	mov 	dx, [ebx]
  2410                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2411                              <1> 	; 09/01/2022
  2412 00005174 09D2                <1> 	or	edx, edx
  2413                              <1> 	;or 	dx, dx
  2414 00005176 750D                <1> 	jnz 	short alloc_3 ; 1f
  2415                              <1> 		; bne 1f / branch if any free blocks in this word	
  2416 00005178 6683C010            <1> 	add 	ax, 16
  2417                              <1> 		; add $16.,r1
  2418                              <1> 	; 09/01/2022
  2419 0000517C 39C8                <1> 	cmp	eax, ecx
  2420                              <1> 	;cmp 	ax, cx    
  2421                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2422 0000517E 72EF                <1> 	jb 	short alloc_2
  2423                              <1> 		; blo 1b
  2424                              <1> 	; 14/11/2015
  2425                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2426                              <1> 	;	because of a (DMA or another) r/w error, 
  2427                              <1> 	;	we will be here, at 'jmp panic' code address,
  2428                              <1> 	;	even if the (disk) file system space is not full !!!
  2429                              <1> 	;	(cx = 0)	
  2430                              <1> 	;
  2431 00005180 E901E2FFFF          <1> 	jmp     panic 
  2432                              <1> 		; jmp panic / found no free storage
  2433                              <1> alloc_3: ; 1
  2434                              <1> 	; 09/01/2022
  2435 00005185 D1EA                <1> 	shr	edx, 1
  2436                              <1> 	;shr	dx, 1
  2437                              <1> 		; asr r3 / find a free block
  2438 00005187 7203                <1> 	jc	short alloc_4 ; 1f
  2439                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2440                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2441                              <1> 	; 09/01/2022
  2442 00005189 40                  <1> 	inc	eax
  2443                              <1> 	;inc	ax
  2444                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2445 0000518A EBF9                <1> 	jmp 	short alloc_3
  2446                              <1> 		; br 1b
  2447                              <1> alloc_4: ; 1:
  2448                              <1> 	;; pop cx ;; 01/08/2013
  2449                              <1> 		; tst (sp)+ / bump sp
  2450                              <1> 	; 02/04/2013 
  2451 0000518C E829000000          <1> 	call	free3
  2452                              <1> 		; jsr r0,3f / have found a free block
  2453                              <1> 	; 21/8/2012
  2454 00005191 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2455 00005194 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2456                              <1> 		; bic r3,(r2) / set bit for this block 
  2457                              <1> 		            ; / i.e. assign block
  2458                              <1> 		; br 2f
  2459 00005197 EB09                <1> 	jmp 	short alloc_5
  2460                              <1> 
  2461                              <1> free:
  2462                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2463                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2464                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2465                              <1> 	;
  2466                              <1> 	; calculates byte address and bit position for given block number
  2467                              <1> 	; then sets the corresponding bit in the free storage map
  2468                              <1> 	; 
  2469                              <1> 	; INPUTS ->
  2470                              <1> 	;    r1 - block number for a block structured device
  2471                              <1> 	;    cdev - current device 
  2472                              <1> 	; OUTPUTS ->
  2473                              <1> 	;    free storage map is updated
  2474                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2475                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2476                              <1> 	;
  2477                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2478                              <1>         ;  ((Modified registers: DX, CX))  
  2479                              <1> 
  2480                              <1> 		;mov r2,-(sp) / save r2, r3
  2481                              <1> 		;mov r3,-(sp)
  2482                              <1> 	;push 	ecx
  2483 00005199 53                  <1> 	push 	ebx ; R2
  2484                              <1> 	;push 	edx ; R3 
  2485                              <1> 
  2486 0000519A E81B000000          <1>         call    free3
  2487                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2488                              <1> 				 ; / in free storage map for block
  2489 0000519F 660913              <1> 	or 	[ebx], dx  
  2490                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2491                              <1> 			    ;  / indicates free block	
  2492                              <1> 	; 0 -> allocated, 1 -> free
  2493                              <1> 
  2494                              <1> alloc_5:
  2495                              <1> 	; 07/04/2013
  2496                              <1> free_1: ; 2:
  2497                              <1> 	;pop 	edx
  2498                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2499 000051A2 5B                  <1> 	pop	ebx
  2500                              <1> 		; mov (sp)+,r2
  2501                              <1> 	; pop	ecx
  2502 000051A3 803D[2F6F0000]00    <1> 	cmp 	byte [cdev], 0
  2503                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2504                              <1> 			 ; / cdev = 1, mountable device
  2505 000051AA 7707                <1> 	ja	short alloc_6 ; 1f
  2506                              <1> 		; bne 1f
  2507                              <1> 	;mov	byte [smod], 1
  2508 000051AC FE05[3F6F0000]      <1> 	inc 	byte [smod]
  2509                              <1> 		; incb smod / set super block modified for drum
  2510                              <1> 	; eAX (r1) = block number
  2511 000051B2 C3                  <1> 	retn
  2512                              <1> 		; rts r0
  2513                              <1> free_2:
  2514                              <1> alloc_6: ; 1:
  2515                              <1> 	;mov 	byte [mmod], 1
  2516 000051B3 FE05[406F0000]      <1> 	inc 	byte [mmod]
  2517                              <1> 		; incb	mmod 
  2518                              <1> 		  ; / set super block modified for mountable device
  2519                              <1> 	; eAX (r1) = block number
  2520 000051B9 C3                  <1> 	retn	
  2521                              <1> 		; rts r0
  2522                              <1> free3:
  2523                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2524                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2525                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2526                              <1> 	;
  2527                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2528                              <1> 	; 
  2529                              <1> alloc_free_3: ; 3
  2530                              <1> 	;mov 	dx, 1
  2531                              <1> 	; 09/01/2022
  2532 000051BA 31D2                <1> 	xor	edx, edx
  2533 000051BC 42                  <1> 	inc	edx
  2534                              <1> 	; edx = 1
  2535 000051BD 88C1                <1> 	mov 	cl, al
  2536                              <1> 		; mov r1,r2 / block number, k, = 1		
  2537 000051BF 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2538                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2539 000051C2 7402                <1> 	jz 	short free4
  2540                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2541                              <1> 			       ; / (k) mod 8
  2542                              <1> 	;shl 	dx, cl
  2543                              <1> 	; 09/01/2022
  2544 000051C4 D3E2                <1> 	shl	edx, cl
  2545                              <1> free4:
  2546 000051C6 0FB7D8              <1> 	movzx 	ebx, ax
  2547                              <1> 		; mov r1,r2 / divide block number by 16
  2548                              <1> 	; 09/01/2022
  2549 000051C9 C1EB04              <1> 	shr	ebx, 4
  2550                              <1> 	;shr 	bx, 4
  2551                              <1> 		; asr r2
  2552                              <1> 		; asr r2
  2553                              <1> 		; asr r2
  2554                              <1> 		; asr r2
  2555                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2556                              <1> 		       ; / bit for block is in lower half of word
  2557                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2558                              <1> 		        ; / storage map
  2559                              <1> alloc_free_4: ; 1
  2560                              <1> 	; 09/01/2022
  2561 000051CC D1E3                <1> 	shl	ebx, 1
  2562                              <1> 	;shl 	bx, 1
  2563                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2564 000051CE 81C3[0E7C0000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2565                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2566                              <1> 	    		        ; / with block bit in it 	
  2567 000051D4 803D[2F6F0000]00    <1> 	cmp	byte [cdev], 0
  2568                              <1> 		; tst cdev
  2569 000051DB 7606                <1> 	jna	short alloc_free_5
  2570                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2571 000051DD 81C308020000        <1> 	add	ebx, mount - systm
  2572                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2573                              <1> 				    ; / mountable device with bit of block to be
  2574                              <1> 				    ; / freed
  2575                              <1> alloc_free_5: ; 1 
  2576 000051E3 C3                  <1> 	retn
  2577                              <1> 		; rts r0 / return to 'free'
  2578                              <1> 	      ; 2
  2579                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2580                              <1> 	
  2581                              <1> iget:
  2582                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2583                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2584                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2585                              <1> 	;
  2586                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2587                              <1> 	;
  2588                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2589                              <1> 	; 
  2590                              <1> 	; INPUTS ->
  2591                              <1> 	;    ii - current i-number, rootdir
  2592                              <1> 	;    cdev - new i-node device
  2593                              <1> 	;    idev - current i-node device
  2594                              <1> 	;    imod - current i-node modified flag
  2595                              <1> 	;    mnti - cross device file i-number
  2596                              <1> 	;    r1 - i-numbe rof new i-node
  2597                              <1> 	;    mntd - mountable device number		
  2598                              <1> 	; 	 
  2599                              <1> 	; OUTPUTS ->
  2600                              <1> 	;    cdev, idev, imod, ii, r1
  2601                              <1> 	;
  2602                              <1> 	; ((AX = R1)) input/output
  2603                              <1> 	;
  2604                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2605                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2606                              <1> 
  2607 000051E4 8A15[2F6F0000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2608 000051EA 8A35[2E6F0000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2609                              <1> 	;
  2610 000051F0 663B05[2C6F0000]    <1> 	cmp 	ax, [ii]
  2611                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2612 000051F7 7504                <1> 	jne 	short iget_1
  2613                              <1> 		; bne 1f
  2614 000051F9 38F2                <1> 	cmp	dl, dh
  2615                              <1> 		; cmp idev,cdev
  2616                              <1> 			  ; / is device number of i-node = current device
  2617 000051FB 7472                <1>         je      short iget_5
  2618                              <1> 		; beq 2f
  2619                              <1> iget_1: ; 1:
  2620 000051FD 30DB                <1> 	xor	bl, bl
  2621 000051FF 381D[3E6F0000]      <1> 	cmp	[imod], bl ; 0	
  2622                              <1> 		; tstb imod / has i-node of current file
  2623                              <1> 			  ; / been modified i.e., imod set
  2624 00005205 7629                <1> 	jna	short iget_2
  2625                              <1> 		; beq 1f
  2626 00005207 881D[3E6F0000]      <1> 	mov	[imod], bl ; 0
  2627                              <1> 		;  clrb	imod / if it has, 
  2628                              <1> 			   ; / we must write the new i-node out on disk
  2629                              <1> 	; 24/12/2021
  2630 0000520D 50                  <1> 	push	eax ; *
  2631                              <1> 	;push	ax
  2632                              <1> 		; mov r1,-(sp)
  2633                              <1> 	;mov	dl, [cdev]
  2634 0000520E 52                  <1> 	push	edx ; **
  2635                              <1> 	;push	dx
  2636                              <1> 		; mov cdev,-(sp)
  2637 0000520F 66A1[2C6F0000]      <1> 	mov	ax, [ii]
  2638                              <1> 		; mov ii,r1
  2639                              <1> 	;mov	dh, [idev]
  2640 00005215 8835[2F6F0000]      <1> 	mov	[cdev], dh
  2641                              <1> 		; mov idev,cdev
  2642 0000521B FEC3                <1> 	inc	bl ; 1
  2643                              <1> 	; 31/07/2013
  2644 0000521D 881D[D06F0000]      <1> 	mov     [rw], bl ; 1 == write 
  2645                              <1> 	;;28/07/2013 rw -> u.rw
  2646                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2647 00005223 E848000000          <1> 	call	icalc
  2648                              <1> 		; jsr r0,icalc; 1
  2649                              <1> 	;pop	dx
  2650                              <1> 	; 24/12/2021
  2651 00005228 5A                  <1> 	pop	edx ; **
  2652 00005229 8815[2F6F0000]      <1> 	mov	[cdev], dl
  2653                              <1> 		; mov (sp)+,cdev
  2654                              <1> 	; 24/12/2021
  2655 0000522F 58                  <1> 	pop	eax ; *
  2656                              <1> 	;pop	ax
  2657                              <1> 		; mov (sp)+,r1
  2658                              <1> iget_2: ; 1:
  2659 00005230 6621C0              <1> 	and	ax, ax
  2660                              <1> 		; tst r1 / is new i-number non zero
  2661 00005233 7434                <1> 	jz	short iget_4 ; 2f
  2662                              <1> 		; beq 2f / branch if r1=0
  2663                              <1> 
  2664                              <1> 	;mov 	dl, [cdev]
  2665 00005235 08D2                <1> 	or	dl, dl
  2666                              <1> 		; tst cdev / is the current device number non zero
  2667                              <1> 			 ; / (i.e., device =/ drum)
  2668 00005237 7517                <1> 	jnz	short iget_3 ;  1f
  2669                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2670 00005239 663B05[346F0000]    <1> 	cmp	ax, [mnti]			
  2671                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2672                              <1> 			    ; / file (root directory of mounted device)
  2673 00005240 750E                <1> 	jne	short iget_3 ; 1f
  2674                              <1> 		; bne 1f
  2675                              <1>         ;mov    bl, [mntd]
  2676 00005242 FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2677 00005244 8815[2F6F0000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2678                              <1> 		; mov mntd,cdev / make mounted device the current device
  2679 0000524A 66A1[3A6F0000]      <1> 	mov	ax, [rootdir]
  2680                              <1> 		; mov rootdir,r1
  2681                              <1> iget_3: ; 1:
  2682 00005250 66A3[2C6F0000]      <1> 	mov	[ii], ax
  2683                              <1> 		; mov r1,ii
  2684 00005256 8815[2E6F0000]      <1> 	mov	[idev], dl ; cdev
  2685                              <1> 		; mov cdev,idev
  2686 0000525C 30DB                <1> 	xor	bl, bl
  2687                              <1>         ; 31/07/2013
  2688 0000525E 881D[D06F0000]      <1> 	mov     [rw], bl ; 0 == read 
  2689                              <1> 	;;28/07/2013 rw -> u.rw       
  2690                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2691 00005264 E807000000          <1> 	call	icalc
  2692                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2693                              <1> iget_4: ; 2:
  2694 00005269 66A1[2C6F0000]      <1> 	mov	ax, [ii]
  2695                              <1> 		; mov ii,r1
  2696                              <1> iget_5:
  2697 0000526F C3                  <1> 	retn
  2698                              <1> 		; rts r0
  2699                              <1> 
  2700                              <1> icalc:
  2701                              <1> 	; 04/04/2022 (47->31)
  2702                              <1> 	;	(Inode Table/List Address modification)
  2703                              <1> 	; 09/01/2022
  2704                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2705                              <1> 	; 02/07/2015
  2706                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2707                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2708                              <1> 	;
  2709                              <1> 	; calculate physical block number from i-number then
  2710                              <1> 	; read or write that block
  2711                              <1> 	;
  2712                              <1> 	; 'icalc' is called from 'iget'
  2713                              <1> 	;
  2714                              <1> 	; for original unix v1:
  2715                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2716                              <1>        	; / (i+31.) mod 16. bytes from its start
  2717                              <1> 	;
  2718                              <1> 	; for retro unix 8086 v1:
  2719                              <1> 	;  i-node is located in block (i+47)/16 and
  2720                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2721                              <1> 	;
  2722                              <1> 	; INPUTS ->
  2723                              <1> 	;    r1 - i-number of i-node
  2724                              <1> 	; 	 
  2725                              <1> 	; OUTPUTS ->
  2726                              <1> 	;    inode r/w
  2727                              <1> 	;
  2728                              <1> 	; ((AX = R1)) input
  2729                              <1> 	;
  2730                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2731                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2732                              <1> 	;
  2733 00005270 0FB7D0              <1> 	movzx	edx, ax	
  2734                              <1> 	;add	dx, 47
  2735                              <1> 	; 04/04/2022
  2736 00005273 6683C21F            <1> 	add	dx, 31
  2737 00005277 89D0                <1> 	mov	eax, edx
  2738                              <1> 	;;add	ax, 47	; add 47 to inode number
  2739                              <1> 	;add	ax, 31
  2740                              <1> 		; add $31.,r1 / add 31. to i-number
  2741 00005279 50                  <1> 	push	eax
  2742                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2743                              <1> 	; 09/01/2022
  2744 0000527A C1E804              <1> 	shr	eax, 4
  2745                              <1> 	;shr 	ax, 4
  2746                              <1> 		; asr r1 / divide by 16.
  2747                              <1> 		; asr r1
  2748                              <1> 		; asr r1
  2749                              <1> 		; asr r1 / r1 contains block number of block
  2750                              <1> 		       ; / in which i-node exists
  2751 0000527D E89F0A0000          <1> 	call	dskrd
  2752                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2753                              <1> 	; 31/07/2013
  2754 00005282 803D[D06F0000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2755                              <1> 	;; 28/07/2013 rw -> u.rw
  2756                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2757                              <1> 		; tst (r0)
  2758 00005289 7605                <1> 	jna	short icalc_1
  2759                              <1> 		; beq 1f / branch to wslot when argument
  2760                              <1> 		       ; / in icalc call = 1
  2761                              <1> 	; eAX = r1 = block number
  2762 0000528B E8030B0000          <1> 	call	wslot
  2763                              <1> 		; jsr r0,wslot / set up data buffer for write
  2764                              <1> 			     ; / (will be same buffer as dskrd got)
  2765                              <1> 	; eBX = r5 points to first word in data area for this block
  2766                              <1> icalc_1: ; 1:
  2767 00005290 5A                  <1> 	pop	edx 
  2768 00005291 83E20F              <1> 	and 	edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16
  2769                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2770                              <1> 			      ; / gives (i+31.) mod 16
  2771 00005294 C1E205              <1> 	shl 	edx, 5
  2772                              <1> 	; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16)
  2773 00005297 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2774 00005299 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2775                              <1>           	; eSI (r5) points to first word in i-node i.	
  2776                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2777                              <1> 			     ; / 32.*(i+31.)mod16
  2778                              <1> 		; mov $5,lsh / for i-node i.
  2779                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2780 0000529B BF[486C0000]        <1> 	mov	edi, inode
  2781                              <1> 		; mov $inode,r1 / inode is address of first word 
  2782                              <1> 			      ; / of current i-node
  2783                              <1> 	; 09/01/2022
  2784 000052A0 29C9                <1> 	sub	ecx, ecx
  2785 000052A2 B108                <1> 	mov	cl, 8 
  2786                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2787                              <1> 		; mov $16.,r3
  2788                              <1>        ; 31/07/2013
  2789 000052A4 382D[D06F0000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2790                              <1>        ;;28/07/2013 rw -> u.rw                 
  2791                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2792                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2793 000052AA 7609                <1> 	jna	short icalc_3
  2794                              <1> 		; beq 2f / r0 now contains proper return address 
  2795                              <1> 		       ; / for rts r0
  2796                              <1> icalc_2: ; 1:
  2797 000052AC 87F7                <1> 	xchg 	esi, edi
  2798                              <1> 	; overwrite old i-node (in buffer to be written)
  2799 000052AE F3A5                <1> 	rep 	movsd
  2800                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2801                              <1> 		; dec r3
  2802                              <1> 		; bgt 1b
  2803                              <1> 	;call	dskwr
  2804                              <1> 		; jsr r0,dskwr / write inode out on device
  2805                              <1> 	;retn
  2806                              <1> 		; rts r0
  2807                              <1> 	; 24/12/2021
  2808 000052B0 E9FA0A0000          <1> 	jmp	dskwr
  2809                              <1> 
  2810                              <1> icalc_3: ; 2:
  2811                              <1> 	; copy new i-node into inode area of (core) memory
  2812 000052B5 F3A5                <1> 	rep 	movsd
  2813                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2814                              <1> 		                ; / "inode" area of core
  2815                              <1> 		; dec r3
  2816                              <1> 		; bgt 2b
  2817 000052B7 C3                  <1> 	retn
  2818                              <1> 		; rts r0
  2819                              <1> 
  2820                              <1> access:
  2821                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2822                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2823                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2824                              <1> 	;
  2825                              <1> 	; check whether user is owner of file or user has read or write
  2826                              <1> 	; permission (based on i.flgs).
  2827                              <1> 	;
  2828                              <1> 	; INPUTS ->
  2829                              <1> 	;    r1 - i-number of file
  2830                              <1> 	;    u.uid
  2831                              <1> 	; arg0 -> (owner flag mask)	 		
  2832                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2833                              <1> 	; OUTPUTS ->
  2834                              <1> 	;    inode (or jump to error)
  2835                              <1> 	;
  2836                              <1> 	; ((AX = R1)) input/output
  2837                              <1> 	;
  2838                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2839                              <1> 	
  2840                              <1> 	;push	dx  ; save flags (DL)
  2841                              <1> 	; 24/12/2021
  2842 000052B8 52                  <1> 	push	edx ; save flags (DL)
  2843 000052B9 E826FFFFFF          <1> 	call	iget
  2844                              <1> 		; jsr r0,iget / read in i-node for current directory
  2845                              <1> 			    ; / (i-number passed in r1)
  2846 000052BE 8A0D[486C0000]      <1> 	mov	cl, [i.flgs]
  2847                              <1> 		; mov i.flgs,r2
  2848                              <1> 	; 24/12/2021
  2849 000052C4 5A                  <1> 	pop	edx ; restore flags (DL)
  2850                              <1> 	;pop	dx  ; restore flags (DL)
  2851 000052C5 8A35[986F0000]      <1> 	mov	dh, [u.uid]
  2852 000052CB 3A35[4B6C0000]      <1> 	cmp	dh, [i.uid]
  2853                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2854 000052D1 7503                <1> 	jne	short access_1
  2855                              <1> 		; bne 1f / no, then branch
  2856 000052D3 C0E902              <1> 	shr	cl, 2
  2857                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2858                              <1> 		        ; / read/write bits
  2859                              <1> 		; asrb r2
  2860                              <1> access_1: ; 1:
  2861 000052D6 20D1                <1> 	and	cl, dl
  2862                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2863                              <1> 			     ; / in access call
  2864 000052D8 7513                <1> 	jnz	short access_2
  2865                              <1> 		; bne 1f
  2866 000052DA 08F6                <1> 	or	dh, dh	; super user (root) ?
  2867                              <1> 		; tstb u.uid
  2868 000052DC 740F                <1> 	jz	short access_2 ; yes, super user
  2869                              <1> 	;jnz	error
  2870                              <1> 		; beq 1f
  2871                              <1> 		; jmp error
  2872 000052DE C705[A16F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2872 000052E6 0000                <1>
  2873                              <1> 			; 'permission denied !' error
  2874 000052E8 E9DAE7FFFF          <1> 	jmp	error
  2875                              <1> 
  2876                              <1> access_2: ; 1:
  2877                              <1> 	; DL = flags
  2878 000052ED C3                  <1> 	retn
  2879                              <1> 		; rts r0
  2880                              <1> 
  2881                              <1> setimod:
  2882                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2883                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2884                              <1> 	;
  2885                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2886                              <1> 	; the inode has been modified. Also puts the time of modification
  2887                              <1> 	; into the inode.
  2888                              <1> 	;
  2889                              <1> 	; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2890                              <1>         ; ((Modified registers: eDX, eCX, eBX)) 
  2891                              <1> 	;
  2892                              <1> 	
  2893                              <1> 	;push 	edx
  2894 000052EE 50                  <1> 	push	eax
  2895                              <1> 
  2896 000052EF C605[3E6F0000]01    <1> 	mov 	byte [imod], 1
  2897                              <1> 		; movb $1,imod / set current i-node modified bytes
  2898                              <1> 	; Erdogan Tan 14-7-2012
  2899 000052F6 E81AE3FFFF          <1> 	call 	epoch
  2900                              <1> 		 ; mov s.time,i.mtim 
  2901                              <1> 			    ; / put present time into file modified time
  2902                              <1> 		 ; mov s.time+2,i.mtim+2
  2903                              <1> 
  2904 000052FB A3[626C0000]        <1> 	mov 	[i.mtim], eax
  2905                              <1> 	
  2906                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2907                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2908 00005300 833D[5E6C0000]00    <1> 	cmp	dword [i.ctim], 0
  2909 00005307 7505                <1> 	jnz	short setimod_ok
  2910                              <1> 
  2911 00005309 A3[5E6C0000]        <1> 	mov 	[i.ctim], eax
  2912                              <1> 
  2913                              <1> setimod_ok: ; 31/07/2013
  2914 0000530E 58                  <1> 	pop	eax
  2915                              <1> 	;pop	edx
  2916                              <1> 	
  2917 0000530F C3                  <1> 	retn
  2918                              <1> 		; rts r0
  2919                              <1> 
  2920                              <1> itrunc:
  2921                              <1> 	; 03/02/2022
  2922                              <1> 	; 09/01/2022
  2923                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1) 
  2924                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2925                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2926                              <1> 	;
  2927                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2928                              <1> 	;  to zero length.
  2929                              <1> 	;
  2930                              <1> 	; INPUTS ->
  2931                              <1> 	;    r1 - i-number of i-node
  2932                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2933                              <1> 	;    i.flgs - large file flag		
  2934                              <1> 	;    i.size - size of file	
  2935                              <1> 	; 	 
  2936                              <1> 	; OUTPUTS ->
  2937                              <1> 	;    i.flgs - large file flag is cleared
  2938                              <1> 	;    i.size - set to 0	
  2939                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2940                              <1> 	;    setimod - set to indicate i-node has been modified
  2941                              <1> 	;    r1 - i-number of i-node  					
  2942                              <1> 	;
  2943                              <1> 	; ((AX = R1)) input/output
  2944                              <1> 	;
  2945                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2946                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2947                              <1> 
  2948 00005310 E8CFFEFFFF          <1> 	call	iget
  2949                              <1> 		; jsr r0,iget
  2950 00005315 BE[4E6C0000]        <1> 	mov	esi, i.dskp
  2951                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2952 0000531A 31C0                <1> 	xor	eax, eax
  2953                              <1> itrunc_1: ; 1:
  2954 0000531C 66AD                <1> 	lodsw
  2955                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2956                              <1> 	; 09/01/2022
  2957 0000531E 09C0                <1> 	or	eax, eax
  2958                              <1> 	;or 	ax, ax
  2959 00005320 7433                <1> 	jz	short itrunc_5
  2960                              <1> 		; beq 5f
  2961 00005322 56                  <1> 	push	esi
  2962                              <1> 		; mov r2,-(sp)
  2963                              <1> 	; 09/01/2022
  2964 00005323 F605[496C0000]10    <1> 	test	byte [i.flgs+1], 10h
  2965                              <1> 	;test	word [i.flgs], 1000h
  2966                              <1> 		; bit $10000,i.flgs / test large file bit?
  2967 0000532A 7423                <1> 	jz	short itrunc_4
  2968                              <1> 		; beq 4f / if clear, branch
  2969 0000532C 50                  <1> 	push	eax
  2970                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2971 0000532D E8EF090000          <1> 	call	dskrd
  2972                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2973                              <1> 			     ; / pointed to by r5
  2974                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2975                              <1> 	; 09/01/2022
  2976 00005332 31C9                <1> 	xor	ecx, ecx
  2977 00005334 FEC5                <1> 	inc	ch ; mov ch, 1
  2978                              <1> 	; ecx = 256
  2979                              <1> 	;mov	ecx, 256
  2980                              <1> 		; mov $256.,r3 / move word count into r3
  2981 00005336 89DE                <1> 	mov	esi, ebx
  2982                              <1> itrunc_2: ; 2:
  2983 00005338 66AD                <1> 	lodsw
  2984                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2985                              <1> 			     ; / physical block number
  2986                              <1> 	; 09/01/2022
  2987 0000533A 21C0                <1> 	and	eax, eax
  2988                              <1> 	;and	ax, ax
  2989 0000533C 7407                <1> 	jz	short itrunc_3
  2990                              <1> 		; beq 3f / branch if zero
  2991                              <1> 	; 24/12/2021
  2992 0000533E 51                  <1> 	push	ecx
  2993                              <1> 	;push	cx
  2994                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  2995                              <1> 	;push	esi
  2996                              <1> 		; mov r5,-(sp)
  2997 0000533F E855FEFFFF          <1> 	call	free
  2998                              <1> 		; jsr r0,free / free block in free storage map
  2999                              <1> 	;pop	esi
  3000                              <1> 		; mov(sp)+,r5
  3001                              <1> 	;pop	cx
  3002 00005344 59                  <1> 	pop	ecx
  3003                              <1> 		; mov (sp)+,r3
  3004                              <1> itrunc_3: ; 3:
  3005 00005345 E2F1                <1> 	loop	itrunc_2
  3006                              <1> 		; dec r3 / decrement word count
  3007                              <1> 		; bgt 2b / branch if positive
  3008 00005347 58                  <1> 	pop	eax
  3009                              <1> 		; mov (sp)+,r1 / put physical block number of 
  3010                              <1> 			     ; / indirect block
  3011                              <1> 	; 01/08/2013
  3012                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3013                              <1> 	; 03/02/2022
  3014 00005348 8025[496C0000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  3015                              <1> itrunc_4: ; 4:
  3016 0000534F E845FEFFFF          <1> 	call	free
  3017                              <1> 		; jsr r0,free / free indirect block
  3018 00005354 5E                  <1> 	pop	esi
  3019                              <1> 		; mov (sp)+,r2
  3020                              <1> itrunc_5: ; 5:
  3021 00005355 81FE[5E6C0000]      <1> 	cmp	esi, i.dskp+16
  3022                              <1> 		; cmp r2,$i.dskp+16.
  3023 0000535B 72BF                <1> 	jb	short itrunc_1	
  3024                              <1> 		; bne 1b / branch until all i.dskp entries check
  3025                              <1> 	; 03/02/2022
  3026                              <1> 	;and	byte [i.flgs+1], 0EFh
  3027                              <1> 	; 01/08/2013
  3028                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3029                              <1> 		; bic $10000,i.flgs / clear large file bit
  3030 0000535D BF[4E6C0000]        <1> 	mov	edi, i.dskp
  3031                              <1> 	;mov	cx, 8
  3032                              <1> 	;xor 	ax, ax
  3033                              <1> 	; 09/01/2022
  3034 00005362 29C9                <1> 	sub	ecx, ecx
  3035 00005364 B108                <1> 	mov	cl, 8
  3036 00005366 29C0                <1> 	sub	eax, eax
  3037 00005368 66A3[4C6C0000]      <1> 	mov	[i.size], ax ; 0
  3038                              <1> 		; clr i.size / zero file size
  3039 0000536E F366AB              <1> 	rep	stosw
  3040                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  3041                              <1> 			   ; / zero block pointers
  3042 00005371 E878FFFFFF          <1> 	call	setimod
  3043                              <1> 		; jsr r0,setimod / set i-node modified flag
  3044 00005376 66A1[2C6F0000]      <1> 	mov	ax, [ii]
  3045                              <1> 		; mov ii,r1
  3046 0000537C C3                  <1> 	retn
  3047                              <1> 		; rts r0
  3048                              <1> 
  3049                              <1> imap:
  3050                              <1> 	; 11/02/2022
  3051                              <1> 	; 03/02/2022
  3052                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3053                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3054                              <1> 	;
  3055                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3056                              <1> 	; allocation bit for an i-node whose number in r1.
  3057                              <1> 	;
  3058                              <1> 	; INPUTS ->
  3059                              <1> 	;    r1 - contains an i-number
  3060                              <1> 	;    fsp - start of table containing open files
  3061                              <1> 	;
  3062                              <1> 	; OUTPUTS ->
  3063                              <1> 	;    r2 - byte address of byte with the allocation bit
  3064                              <1> 	;    mq - a mask to locate the bit position.	
  3065                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3066                              <1> 	;
  3067                              <1> 	; ((AX = R1)) input/output
  3068                              <1> 	; ((DL/DX = MQ)) output
  3069                              <1> 	; ((BX = R2)) output
  3070                              <1> 	;
  3071                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3072                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3073                              <1> 	;
  3074                              <1> 		; / get the byte that has the allocation bit for 
  3075                              <1> 		; / the i-number contained in r1
  3076                              <1> 	;mov	dx, 1
  3077 0000537D B201                <1> 	mov	dl, 1
  3078                              <1> 		; mov $1,mq / put 1 in the mq
  3079 0000537F 0FB7D8              <1> 	movzx	ebx, ax
  3080                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3081                              <1>  		          ; / in the map we must find
  3082 00005382 6683EB29            <1> 	sub	bx, 41
  3083                              <1> 		; sub $41.,r2 / r2 has i-41
  3084 00005386 88D9                <1> 	mov	cl, bl
  3085                              <1> 		; mov r2,r3 / r3 has i-41
  3086 00005388 80E107              <1> 	and	cl, 7
  3087                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3088                              <1> 			   ; / the bit position
  3089 0000538B 7402                <1> 	jz	short imap1
  3090                              <1> 	;shl	dx, cl
  3091 0000538D D2E2                <1> 	shl	dl, cl
  3092                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3093                              <1> imap1:			   ; / to the left to mask the correct bit
  3094                              <1> 	; 03/02/2022
  3095 0000538F C1EB03              <1> 	shr	ebx, 3
  3096                              <1> 	;shr	bx, 3
  3097                              <1> 		; asr r2
  3098                              <1> 		; asr r2
  3099                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3100                              <1> 		       ; / from the start of the map
  3101                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3102 00005392 BE[0C7C0000]        <1> 	mov	esi, systm
  3103                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3104                              <1> 				; / the super block for drum
  3105                              <1> 	;cmp	word [cdev], 0
  3106 00005397 803D[2F6F0000]00    <1> 	cmp	byte [cdev], 0
  3107                              <1> 		; tst cdev / is the device the disk
  3108 0000539E 7606                <1> 	jna	short imap2
  3109                              <1> 		; beq 1f / yes
  3110 000053A0 81C608020000        <1> 	add	esi, mount - systm
  3111                              <1> 		; add $mount-systm,r2 / for mounted device,
  3112                              <1> 			; / r2 points to 1st word of its super block
  3113                              <1> imap2: ; 1:
  3114 000053A6 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3115                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3116 000053A9 6683C304            <1> 	add	bx, 4
  3117 000053AD 01F3                <1> 	add	ebx, esi
  3118                              <1>         	; add (sp)+,r2 / ?
  3119                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3120                              <1> 		      ;; (2 + free map size + 2)
  3121                              <1> 		; add $2,r2 / ?
  3122                              <1> 
  3123                              <1> 	; 11/02/2022
  3124 000053AF 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3125 000053B5 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3126                              <1> 			  ; if inode num overs inode count
  3127                              <1> 
  3128                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3129                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3130                              <1> 
  3131                              <1> 	; 11/02/2022
  3132                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3133                              <1> 	;	(number of requested inode > inode count)
  3134                              <1> 
  3135 000053B7 C3                  <1> 	retn
  3136                              <1> 		; rts r0
  2105                                  %include 'u6.s'        ; 31/05/2015
  2106                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS6.INC
  2107                              <1> ; Last Modification: 03/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 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2118                              <1> ;
  2119                              <1> ; ****************************************************************************
  2120                              <1> 
  2121                              <1> readi:
  2122                              <1> 	; 11/01/2022
  2123                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2124                              <1> 	; 20/05/2015
  2125                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2126                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2127                              <1> 	;
  2128                              <1> 	; Reads from an inode whose number in R1
  2129                              <1> 	; 
  2130                              <1> 	; INPUTS ->
  2131                              <1> 	;    r1 - inode number
  2132                              <1> 	;    u.count - byte count user desires
  2133                              <1> 	;    u.base - points to user buffer
  2134                              <1> 	;    u.fofp - points to word with current file offset
  2135                              <1> 	; OUTPUTS ->
  2136                              <1> 	;    u.count - cleared
  2137                              <1> 	;    u.nread - accumulates total bytes passed back
  2138                              <1> 	;
  2139                              <1> 	; ((AX = R1)) input/output
  2140                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2141                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2142                              <1> 
  2143 000053B8 31D2                <1> 	xor	edx, edx ; 0
  2144 000053BA 8915[746F0000]      <1> 	mov 	[u.nread], edx ; 0
  2145                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2146 000053C0 668915[B16F0000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2147 000053C7 3915[706F0000]      <1> 	cmp 	[u.count], edx ; 0
  2148                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2149 000053CD 7701                <1> 	ja 	short readi_1 ; 1f
  2150                              <1> 		 ; bgt 1f / yes, branch
  2151 000053CF C3                  <1> 	retn
  2152                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2153                              <1> readi_1: ; 1:
  2154                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2155 000053D0 6683F828            <1> 	cmp	ax, 40
  2156                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2157                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2158                              <1>         ;ja	dskr 
  2159                              <1> 		 ; ble 1f / yes, branch
  2160                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2161                              <1> 		 ;         / read file with i-node number (r1)
  2162                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2163                              <1> 	; 24/12/2021
  2164 000053D4 7605                <1> 	jna	short readi_3
  2165 000053D6 E9CF000000          <1> 	jmp	dskr
  2166                              <1> readi_3:
  2167                              <1> 	; (20/05/2015)
  2168 000053DB 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2169                              <1> 	; 1:
  2170 000053DC 0FB6D8              <1> 	movzx	ebx, al
  2171                              <1> 	; 11/01/2022
  2172 000053DF C1E302              <1> 	shl	ebx, 2
  2173                              <1> 	;shl	bx, 2
  2174                              <1> 		 ; asl r1 / multiply inode number by 2
  2175 000053E2 81C3[E6530000]      <1> 	add	ebx, readi_2 - 4
  2176 000053E8 FF23                <1> 	jmp	dword [ebx]	
  2177                              <1> 		 ; jmp *1f-2(r1)
  2178                              <1> readi_2: ; 1:
  2179 000053EA [36540000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2180                              <1> 		 ;rtty / tty; r1=2
  2181                              <1> 		 ;rppt / ppt; r1=4
  2182 000053EE [86540000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2183                              <1> 		 ;rmem / mem; r1=6
  2184                              <1> 		 ;rrf0 / rf0
  2185                              <1> 		 ;rrk0 / rk0
  2186                              <1> 		 ;rtap / tap0
  2187                              <1> 		 ;rtap / tap1
  2188                              <1> 		 ;rtap / tap2
  2189                              <1> 		 ;rtap / tap3
  2190                              <1> 		 ;rtap / tap4
  2191                              <1> 		 ;rtap / tap5
  2192                              <1> 		 ;rtap / tap6
  2193                              <1> 		 ;rtap / tap7
  2194 000053F2 [D25B0000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2195 000053F6 [D25B0000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2196 000053FA [D25B0000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2197 000053FE [D25B0000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2198 00005402 [D25B0000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2199 00005406 [D25B0000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2200 0000540A [9B540000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2201 0000540E [82540000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2202                              <1> 		 ;rcvt / tty0
  2203 00005412 [82540000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2204                              <1> 		 ;rcvt / tty1
  2205 00005416 [82540000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2206                              <1> 		 ;rcvt / tty2
  2207 0000541A [82540000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2208                              <1> 		 ;rcvt / tty3
  2209 0000541E [82540000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2210                              <1> 		 ;rcvt / tty4
  2211 00005422 [82540000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2212                              <1> 		 ;rcvt / tty5
  2213 00005426 [82540000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2214                              <1> 		 ;rcvt / tty6
  2215 0000542A [82540000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2216                              <1> 		 ;rcvt / tty7
  2217 0000542E [82540000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2218                              <1> 		 ;rcrd / crd
  2219 00005432 [82540000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2220                              <1> 
  2221                              <1> rtty: ; / read from console tty
  2222                              <1> 	; 11/01/2022
  2223                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2224                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2225                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2226                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2227                              <1> 	;	     must be written immediate on video page (screen)
  2228                              <1> 	;	     when it is required.	
  2229                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2230                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2231                              <1> 	;
  2232                              <1> 	; Console tty buffer is PC keyboard buffer
  2233                              <1> 	; and keyboard-keystroke handling is different than original
  2234                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2235                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2236                              <1> 	;
  2237                              <1> 	; 06/12/2013
  2238 00005436 0FB61D[9B6F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2239 0000543D 8A83[A76C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2240                              <1> rttys:
  2241                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2242                              <1> 	               ; / of the control and status block
  2243                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2244                              <1> 		       ; / tty buffer
  2245                              <1> 	; 28/07/2013
  2246 00005443 A2[A06F0000]        <1> 	mov 	[u.ttyn], al
  2247                              <1> 	; 13/01/2014
  2248 00005448 FEC0                <1> 	inc	al
  2249 0000544A A2[7C6F0000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2250                              <1> rtty_nc: ; 01/02/2014
  2251                              <1> 	; 29/09/2013
  2252                              <1> 	;mov	ecx, 10
  2253                              <1> 	; 11/01/2022
  2254 0000544F 29C9                <1> 	sub	ecx, ecx
  2255 00005451 B10A                <1> 	mov	cl, 10
  2256                              <1> rtty_1: 	; 01/02/2014
  2257                              <1> 	;push 	cx ; 29/09/2013
  2258                              <1> 	; 24/12/2021
  2259 00005453 51                  <1> 	push	ecx
  2260                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2261 00005454 B001                <1> 	mov 	al, 1
  2262 00005456 E8C70B0000          <1> 	call 	getc
  2263                              <1> 	; 24/12/2021
  2264 0000545B 59                  <1> 	pop	ecx
  2265                              <1> 	;pop 	cx ; 29/09/2013	
  2266 0000545C 7516                <1> 	jnz	short rtty_2
  2267                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2268                              <1> 	               ; / of chars. Is this number non-zero?
  2269 0000545E E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2270                              <1> 	; 05/10/2013
  2271 00005460 8A25[A06F0000]      <1> 	mov	ah, [u.ttyn]
  2272                              <1> 	; 29/09/2013
  2273 00005466 E898FBFFFF          <1> 	call	sleep
  2274                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2275                              <1>                 ;           / (120 chars.)
  2276                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2277 0000546B EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2278                              <1> 
  2279                              <1> rtty_idle:
  2280                              <1> 	; 29/07/2013
  2281 0000546D E804FBFFFF          <1> 	call 	idle
  2282 00005472 EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2283                              <1> 	;1:
  2284                              <1> 		; tst 2(r5) / is the number of characters zero
  2285                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2286                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2287                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2288                              <1> 		          ; / contains the next char.
  2289                              <1> 		; dec 2(r5) / decrement the character count
  2290                              <1> rtty_2:
  2291 00005474 30C0                <1> 	xor 	al, al
  2292 00005476 E8A70B0000          <1> 	call 	getc
  2293 0000547B E892000000          <1> 	call	passc
  2294                              <1> 		; jsr r0,passc / move the character to core (user)
  2295                              <1> 	;; 17/10/2015 - 16/07/2015
  2296                              <1> 	; 19/06/2014
  2297                              <1> 	;;jnz	short rtty_nc
  2298 00005480 58                  <1> 	pop	eax  ; (20/05/2015)
  2299 00005481 C3                  <1> 	retn 
  2300                              <1> ;ret1:
  2301                              <1> 		; jmp ret / return to caller via 'ret'
  2302                              <1> 
  2303                              <1> rcvt:   ; < receive/read character from tty >
  2304                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2305                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2306                              <1> 	;
  2307                              <1> 	; Retro UNIX 8086 v1 modification !
  2308                              <1> 	; 
  2309                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2310                              <1> 	;		(exactly different than this one)
  2311                              <1> 	;	was in 'u9.s' file.
  2312                              <1> 	;
  2313 00005482 2C0A                <1> 	sub 	al, 10
  2314                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2315                              <1> 	; 16/07/2013
  2316                              <1> 	; 21/05/2013
  2317 00005484 EBBD                <1>         jmp     short rttys
  2318                              <1>       
  2319                              <1> ;rppt: / read paper tape
  2320                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2321                              <1> ;			 / places
  2322                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2323                              <1> ;		       / also enables read bit in prs
  2324                              <1> ;	jsr	r0,passc / place character in users buffer area
  2325                              <1> ;	br	rppt
  2326                              <1> 
  2327                              <1> rmem: ; / transfer characters from memory to a user area of core
  2328                              <1> 	; 17/10/2015
  2329                              <1> 	; 11/06/2015
  2330                              <1> 	; 24/05/2015
  2331                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2332                              <1> 	;
  2333 00005486 8B35[5C6F0000]      <1> 	mov     esi, [u.fofp]
  2334                              <1> rmem_1:
  2335 0000548C 8B1E                <1>         mov     ebx, [esi]        
  2336                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2337                              <1> 		               ; / to be transferred to user
  2338 0000548E FF06                <1>         inc     dword [esi] ; 17/10/2015
  2339                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2340                              <1> 			    ; / char in memory file
  2341 00005490 8A03                <1> 	mov	al, [ebx]
  2342                              <1> 		; movb (r1),r1 / get character from memory file, 
  2343                              <1> 		             ; / put it in r1
  2344 00005492 E87B000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2345                              <1> 			     ;  / the next byte of the users core area
  2346                              <1> 		; br rmem / continue
  2347 00005497 75F3                <1> 	jnz	short rmem_1
  2348                              <1> ret_:
  2349 00005499 58                  <1> 	pop	eax ; 09/06/2015
  2350 0000549A C3                  <1> 	retn
  2351                              <1> 
  2352                              <1> rlpr:
  2353                              <1> ;1:
  2354                              <1> ;rcrd:
  2355 0000549B C705[A16F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2355 000054A3 0000                <1>
  2356 000054A5 E91DE6FFFF          <1> 	jmp	error
  2357                              <1> 		;jmp	error / see 'error' routine
  2358                              <1> 
  2359                              <1> dskr:
  2360                              <1> 	; 12/10/2015
  2361                              <1> 	; 21/08/2015
  2362                              <1> 	; 25/07/2015
  2363                              <1> 	; 10/07/2015
  2364                              <1> 	; 16/06/2015
  2365                              <1> 	; 31/05/2015
  2366                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2367                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2368                              <1> dskr_0:
  2369 000054AA 50                  <1> 	push	eax
  2370                              <1> 		; mov (sp),r1 / i-number in r1
  2371                              <1> 	; AX = i-number
  2372 000054AB E834FDFFFF          <1> 	call	iget
  2373                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2374 000054B0 0FB715[4C6C0000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2375                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2376 000054B7 8B1D[5C6F0000]      <1> 	mov	ebx, [u.fofp]
  2377 000054BD 2B13                <1> 	sub	edx, [ebx]
  2378                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2379                              <1>         ; 12/10/2015
  2380                              <1> 	; jna     short ret_ 
  2381                              <1> 		; blos ret
  2382 000054BF 7709                <1> 	ja	short dskr_1
  2383                              <1> 	;
  2384                              <1> dskr_retn: ; 12/10/2015
  2385 000054C1 58                  <1> 	pop	eax
  2386 000054C2 C605[B36F0000]00    <1> 	mov	byte [u.kcall], 0
  2387 000054C9 C3                  <1> 	retn	
  2388                              <1> dskr_1: 
  2389 000054CA 3B15[706F0000]      <1> 	cmp     edx, [u.count] 
  2390                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2391                              <1> 			       ; / to carry out read
  2392 000054D0 7306                <1> 	jnb	short dskr_2
  2393                              <1> 		; bhis 1f
  2394 000054D2 8915[706F0000]      <1> 	mov	[u.count], edx
  2395                              <1> 		; mov r2,u.count / no, just read to end of file
  2396                              <1> dskr_2: ; 1:
  2397                              <1> 	; AX = i-number
  2398 000054D8 E89EFBFFFF          <1> 	call	mget
  2399                              <1> 		; jsr r0,mget / returns physical block number of block 
  2400                              <1> 			    ; / in file where offset points
  2401                              <1> 	; eAX = physical block number
  2402 000054DD E83F080000          <1> 	call	dskrd
  2403                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2404                              <1> 			     ; / 1st word of data in buffer
  2405                              <1> 	; 09/06/2015
  2406 000054E2 803D[B36F0000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2407 000054E9 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2408 000054EB 66833D[B16F0000]00  <1> 	cmp	word [u.pcount], 0
  2409 000054F3 7705                <1> 	ja	short dskr_4
  2410                              <1> dskr_3:
  2411                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2412 000054F5 E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2413                              <1> dskr_4:
  2414                              <1> 	; eBX (r5) = system (I/O) buffer address -physical-
  2415 000054FA E8BC020000          <1> 	call	sioreg
  2416                              <1> 		; jsr r0,sioreg
  2417 000054FF 87F7                <1> 	xchg	esi, edi
  2418                              <1> 	; eDI = file (user data) offset
  2419                              <1> 	; eSI = sector (I/O) buffer offset
  2420                              <1> 	; eCX = byte count
  2421 00005501 F3A4                <1> 	rep	movsb
  2422                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2423                              <1> 		                 ; / starting at u.base
  2424                              <1> 		; dec r3
  2425                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2426                              <1> 	; 25/07/2015
  2427                              <1> 	; eax = remain bytes in buffer
  2428                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2429 00005503 09C0                <1> 	or	eax, eax
  2430 00005505 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2431                              <1> 	; 03/08/2013
  2432                              <1> 	;pop	eax
  2433 00005507 390D[706F0000]      <1> 	cmp	[u.count], ecx ; 0
  2434                              <1> 		; tst u.count / all bytes read off disk
  2435                              <1> 		; bne dskr
  2436                              <1> 		; br ret
  2437                              <1>         ;ja	short dskr_0
  2438                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2439                              <1> 	;retn
  2440                              <1> 	; 12/10/2015
  2441 0000550D 76B2                <1> 	jna	short dskr_retn
  2442 0000550F 58                  <1> 	pop	eax  ; (i-node number)
  2443 00005510 EB98                <1> 	jmp	short dskr_0
  2444                              <1> 	
  2445                              <1> passc:
  2446                              <1> 	; 18/10/2015
  2447                              <1> 	; 10/07/2015
  2448                              <1> 	; 01/07/2015
  2449                              <1> 	; 08/06/2015
  2450                              <1> 	; 04/06/2015
  2451                              <1> 	; 20/05/2015
  2452                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2453                              <1> 	;
  2454                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2455                              <1> 	;		      to physical address
  2456 00005512 66833D[B16F0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2457                              <1> 			     ; 1-4095 --> use previous physical base address
  2458                              <1> 			     ; in [u.pbase]
  2459 0000551A 7705                <1> 	ja	short passc_3
  2460                              <1> 	; 08/06/2015 - 10/07/2015
  2461 0000551C E82C000000          <1> 	call	trans_addr_w
  2462                              <1> passc_3:
  2463                              <1> 	; 19/05/2015
  2464 00005521 66FF0D[B16F0000]    <1> 	dec	word [u.pcount]
  2465                              <1> 	;
  2466 00005528 8B1D[AD6F0000]      <1> 	mov	ebx, [u.pbase]
  2467 0000552E 8803                <1> 	mov	[ebx], al
  2468                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2469                              <1> 		               ; / users buffer
  2470 00005530 FF05[6C6F0000]      <1> 	inc	dword [u.base]
  2471                              <1> 		; inc u.base / increment the pointer to point to 
  2472                              <1> 			  ; / the next byte in users buffer
  2473 00005536 FF05[AD6F0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2474 0000553C FF05[746F0000]      <1> 	inc	dword [u.nread]
  2475                              <1> 		; inc u.nread / increment the number of bytes read
  2476 00005542 FF0D[706F0000]      <1> 	dec	dword [u.count]
  2477                              <1> 		; dec u.count / decrement the number of bytes to be read
  2478                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2479 00005548 C3                  <1> 	retn
  2480                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2481                              <1> 		             ; / 'readi' by:
  2482                              <1> 		;/ (1) pop the return address off the stack into r0
  2483                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2484                              <1> 	;1:
  2485                              <1> 		; clr	*$ps / clear processor status
  2486                              <1> 		; rts r0 / return to address currently on top of stack
  2487                              <1> 
  2488                              <1> trans_addr_r:
  2489                              <1> 	; Translate virtual address to physical address 
  2490                              <1> 	; for reading from user's memory space
  2491                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2492                              <1> 	; 18/10/2015
  2493                              <1> 	; 10/07/2015
  2494                              <1> 	; 09/06/2015
  2495                              <1> 	; 08/06/2015 
  2496                              <1> 	; 04/06/2015
  2497                              <1> 	;
  2498                              <1> 	; 18/10/2015
  2499 00005549 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2500 0000554B EB04                <1> 	jmp 	short trans_addr_rw
  2501                              <1> 
  2502                              <1> 	;push	eax
  2503                              <1> 	;push	ebx
  2504                              <1> 	;mov	ebx, [u.base]
  2505                              <1> 	;call	get_physical_addr ; get physical address
  2506                              <1> 	;;jnc	short cpass_0
  2507                              <1> 	;jnc	short passc_1
  2508                              <1> 	;mov	[u.error], eax
  2509                              <1> 	;;pop	ebx
  2510                              <1> 	;;pop	eax
  2511                              <1> 	;jmp	error
  2512                              <1> ;cpass_0:
  2513                              <1> 	; 18/10/2015
  2514                              <1> 	; 20/05/2015
  2515                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2516                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2517                              <1> 	;pop	ebx
  2518                              <1> 	;pop	eax
  2519                              <1> 	;retn	; 08/06/2015
  2520                              <1> 
  2521                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2522                              <1> trans_addr_w:
  2523                              <1> 	; 31/12/2021
  2524                              <1> 	; Translate virtual address to physical address 
  2525                              <1> 	; for writing to user's memory space
  2526                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2527                              <1> 	; 18/10/2015
  2528                              <1> 	; 29/07/2015
  2529                              <1> 	; 10/07/2015
  2530                              <1> 	; 09/06/2015
  2531                              <1> 	; 08/06/2015
  2532                              <1> 	; 04/06/2015 (passc)
  2533                              <1> 	;
  2534                              <1> 	; 18/10/2015
  2535 0000554D 29D2                <1> 	sub	edx, edx
  2536 0000554F FEC2                <1> 	inc	dl ; 1 (write access sign)
  2537                              <1> trans_addr_rw:
  2538 00005551 50                  <1> 	push	eax
  2539 00005552 53                  <1> 	push	ebx
  2540                              <1> 	; 18/10/2015
  2541 00005553 52                  <1> 	push 	edx ; r/w sign (in DL)
  2542                              <1> 	;
  2543 00005554 8B1D[6C6F0000]      <1> 	mov	ebx, [u.base]
  2544 0000555A E843DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2545 0000555F 730A                <1> 	jnc	short passc_0
  2546 00005561 A3[A16F0000]        <1> 	mov	[u.error], eax
  2547                              <1> 	;pop	edx
  2548                              <1> 	;pop 	ebx
  2549                              <1> 	;pop	eax
  2550 00005566 E95CE5FFFF          <1> 	jmp	error
  2551                              <1> passc_0:
  2552 0000556B F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2553 0000556E 5A                  <1> 	pop	edx ; 18/10/2015
  2554 0000556F 7517                <1> 	jnz	short passc_1
  2555                              <1> 	; 18/10/2015
  2556 00005571 20D2                <1> 	and 	dl, dl
  2557 00005573 7413                <1> 	jz	short passc_1
  2558                              <1> 	; 20/05/2015
  2559                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2560                              <1> 	; EBX = linear address
  2561 00005575 51                  <1> 	push 	ecx
  2562 00005576 53                  <1> 	push	ebx ; * ; 31/12/2021 (BugFix)
  2563 00005577 E895DBFFFF          <1> 	call 	copy_page
  2564 0000557C 5B                  <1> 	pop	ebx ; * ; 31/12/2021 (BugFix)
  2565 0000557D 59                  <1> 	pop	ecx
  2566 0000557E 7217                <1> 	jc	short passc_2
  2567                              <1> 	; 24/12/2021
  2568                              <1> 	;push	eax ; physical address of the new/allocated page
  2569                              <1> 	;call	add_to_swap_queue
  2570                              <1> 	;pop	eax
  2571                              <1> 	; 18/10/2015
  2572 00005580 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2573                              <1> 	;mov 	ecx, PAGE_SIZE
  2574                              <1> 	;sub	ecx, ebx 
  2575 00005586 01D8                <1> 	add	eax, ebx  
  2576                              <1> passc_1: 
  2577                              <1> 	; 18/10/2015
  2578                              <1> 	; 20/05/2015
  2579 00005588 A3[AD6F0000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2580 0000558D 66890D[B16F0000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2581 00005594 5B                  <1> 	pop	ebx
  2582 00005595 58                  <1> 	pop	eax
  2583 00005596 C3                  <1> 	retn	; 08/06/2015
  2584                              <1> passc_2:
  2585 00005597 C705[A16F0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2585 0000559F 0000                <1>
  2586                              <1> 	;pop 	ebx
  2587                              <1> 	;pop	eax
  2588 000055A1 E921E5FFFF          <1> 	jmp	error
  2589                              <1> 
  2590                              <1> writei:
  2591                              <1> 	; 03/02/2022
  2592                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2593                              <1> 	; 20/05/2015
  2594                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2595                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2596                              <1> 	;
  2597                              <1> 	; Write data to file with inode number in R1
  2598                              <1> 	; 
  2599                              <1> 	; INPUTS ->
  2600                              <1> 	;    r1 - inode number
  2601                              <1> 	;    u.count - byte count to be written
  2602                              <1> 	;    u.base - points to user buffer
  2603                              <1> 	;    u.fofp - points to word with current file offset
  2604                              <1> 	; OUTPUTS ->
  2605                              <1> 	;    u.count - cleared
  2606                              <1> 	;    u.nread - accumulates total bytes passed back	
  2607                              <1> 	; ((AX = R1))
  2608                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2609                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2610                              <1> 
  2611 000055A6 31C9                <1> 	xor	ecx, ecx
  2612 000055A8 890D[746F0000]      <1> 	mov 	[u.nread], ecx  ; 0
  2613                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2614                              <1> 		            ; / read or write calls
  2615 000055AE 66890D[B16F0000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2616 000055B5 390D[706F0000]      <1> 	cmp 	[u.count], ecx
  2617                              <1> 	;	; tst u.count / test the byte count specified by the user
  2618 000055BB 7701                <1> 	ja 	short writei_1 ; 1f
  2619                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2620 000055BD C3                  <1> 	retn
  2621                              <1> 	;	; rts r0 / no, return - no writing to do
  2622                              <1> writei_1: ;1:
  2623                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2624 000055BE 6683F828            <1> 	cmp 	ax, 40
  2625                              <1> 		; cmp r1,$40.
  2626                              <1> 		; / does the i-node number indicate a special file?
  2627                              <1> 	;ja	dskw 
  2628                              <1> 		; bgt dskw / no, branch to standard file output
  2629                              <1> 	; 24/12/2021
  2630 000055C2 7605                <1> 	jna	short writei_3
  2631 000055C4 E9ED000000          <1> 	jmp	dskw
  2632                              <1> writei_3:
  2633                              <1> 	; (20/05/2015)
  2634 000055C9 50                  <1> 	push	eax ; because subroutines will jump to 'wret'
  2635 000055CA 0FB6D8              <1> 	movzx	ebx, al
  2636                              <1> 	; 03/02/2022
  2637 000055CD C1E302              <1> 	shl	ebx, 2
  2638                              <1> 	;shl	bx, 2
  2639                              <1> 		; asl r1 / yes, calculate the index into the special file
  2640 000055D0 81C3[D4550000]      <1> 	add	ebx, writei_2 - 4
  2641 000055D6 FF23                <1> 	jmp	dword [ebx]	
  2642                              <1> 		; jmp *1f-2(r1)
  2643                              <1> 		; / jump table and jump to the appropriate routine
  2644                              <1> writei_2: ;1:
  2645 000055D8 [24560000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2646                              <1> 		 ;wtty / tty; r1=2
  2647                              <1> 		 ;wppt / ppt; r1=4
  2648 000055DC [86560000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2649                              <1> 		 ;wmem / mem; r1=6
  2650                              <1> 		 ;wrf0 / rf0
  2651                              <1> 		 ;wrk0 / rk0
  2652                              <1> 		 ;wtap / tap0
  2653                              <1> 		 ;wtap / tap1
  2654                              <1> 		 ;wtap / tap2
  2655                              <1> 		 ;wtap / tap3
  2656                              <1> 		 ;wtap / tap4
  2657                              <1> 		 ;wtap / tap5
  2658                              <1> 		 ;wtap / tap6
  2659                              <1> 		 ;wtap / tap7
  2660 000055E0 [5B5C0000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2661 000055E4 [5B5C0000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2662 000055E8 [5B5C0000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2663 000055EC [5B5C0000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2664 000055F0 [5B5C0000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2665 000055F4 [5B5C0000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2666 000055F8 [77560000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2667 000055FC [71560000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2668                              <1> 		 ;xmtt / tty0
  2669 00005600 [71560000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2670                              <1> 		 ;xmtt / tty1
  2671 00005604 [71560000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2672                              <1> 		 ;xmtt / tty2
  2673 00005608 [71560000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2674                              <1> 		 ;xmtt / tty3
  2675 0000560C [71560000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2676                              <1> 		 ;xmtt / tty4
  2677 00005610 [71560000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2678                              <1> 		 ;xmtt / tty5
  2679 00005614 [71560000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2680                              <1> 		 ;xmtt / tty6
  2681 00005618 [71560000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2682                              <1> 		 ;xmtt / tty7
  2683 0000561C [71560000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2684                              <1> 		; / wlpr / lpr
  2685 00005620 [71560000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2686                              <1> 
  2687                              <1> wtty: ; write to console tty (write to screen)
  2688                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2689                              <1> 	; 18/11/2015
  2690                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2691                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2692                              <1> 	;
  2693                              <1> 	; Console tty output is on current video page
  2694                              <1> 	; Console tty character output procedure is changed here
  2695                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2696                              <1> 	;
  2697 00005624 0FB61D[9B6F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2698 0000562B 8AA3[A76C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2699 00005631 88E0                <1> 	mov	al, ah ; 07/07/2014
  2700                              <1> wttys:	
  2701                              <1> 	; 10/10/2013
  2702 00005633 8825[A06F0000]      <1> 	mov 	[u.ttyn], ah
  2703                              <1> 	; 13/01/2014
  2704 00005639 FEC0                <1> 	inc	al
  2705 0000563B A2[7D6F0000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2706                              <1> wtty_nc: ; 15/05/2013
  2707                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2708 00005640 E816010000          <1> 	call	cpass
  2709                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2710                              <1> 		             ; / none go to return address in syswrite
  2711                              <1> 		; tst r1 / is character = null
  2712                              <1> 		; beq wtty / yes, get next character
  2713                              <1> 	; 10/10/2013
  2714 00005645 7428                <1> 	jz	short wret
  2715                              <1> 	;1 : 
  2716                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2717                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2718                              <1> 		;	          / than 20
  2719                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2720                              <1> 	; 27/06/2014
  2721                              <1> wtty_1:
  2722                              <1> 	; AH = tty number
  2723                              <1> 	; AL = ASCII code of the character
  2724                              <1> 	; 15/04/2014
  2725                              <1> 	;push	ax
  2726                              <1> 	; 24/12/2021
  2727 00005647 50                  <1> 	push	eax
  2728 00005648 E8430A0000          <1> 	call	putc ; 14/05/2013
  2729 0000564D 731D                <1> 	jnc	short wtty_2
  2730                              <1> 	; 18/11/2015
  2731 0000564F E822F9FFFF          <1> 	call	idle
  2732                              <1> 	;mov	ax, [esp]
  2733                              <1> 	; 24/12/2021
  2734 00005654 8B0424              <1> 	mov	eax, [esp]
  2735 00005657 E8340A0000          <1> 	call	putc
  2736 0000565C 730E                <1> 	jnc	short wtty_2 
  2737                              <1> 	; 02/06/2014
  2738 0000565E 8A25[A06F0000]      <1> 	mov	ah, [u.ttyn]
  2739 00005664 E89AF9FFFF          <1> 	call	sleep
  2740                              <1> 	;pop	ax
  2741                              <1> 	; 24/12/2021
  2742 00005669 58                  <1> 	pop	eax
  2743 0000566A EBDB                <1> 	jmp 	short wtty_1
  2744                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2745                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2746                              <1> 			      ; / console tty and
  2747                              <1> 		; br 	2f / place character in list; if none available
  2748                              <1> 		   	  ; / branch to put process to sleep
  2749                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2750                              <1> wtty_2:
  2751                              <1> 	; 15/04/2014
  2752                              <1> 	;pop	ax
  2753                              <1> 	; 24/12/2021
  2754 0000566C 58                  <1> 	pop	eax
  2755 0000566D EBD1                <1> 	jmp	short wtty_nc
  2756                              <1> 		; br wtty
  2757                              <1> wret:	; 10/10/2013 (20/05/2015)
  2758 0000566F 58                  <1> 	pop	eax
  2759 00005670 C3                  <1> 	retn
  2760                              <1> 	;2:
  2761                              <1> 		;mov	r1,-(sp) / place character on stack
  2762                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2763                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2764                              <1> 		;br	1b / try again to place character in clist and output
  2765                              <1> 
  2766                              <1> xmtt:   ; < send/write character to tty >
  2767                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2768                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2769                              <1> 	;
  2770                              <1> 	; Retro UNIX 8086 v1 modification !
  2771                              <1> 	; 
  2772                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2773                              <1> 	;		(exactly different than this one)
  2774                              <1> 	;	was in 'u9.s' file.
  2775                              <1> 	;
  2776 00005671 2C0A                <1> 	sub 	al, 10
  2777                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2778                              <1> 	; 10/10/2013
  2779 00005673 88C4                <1> 	mov	ah, al
  2780                              <1> 	; 28/07/2013
  2781 00005675 EBBC                <1> 	jmp	short wttys
  2782                              <1> 
  2783                              <1> ;wppt:
  2784                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2785                              <1> ;		         / if none return to writei's calling routine
  2786                              <1> ;	jsr	r0,pptoc / output character on ppt
  2787                              <1> ;	br	wppt
  2788                              <1> wlpr:
  2789 00005677 C705[A16F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2789 0000567F 0000                <1>
  2790 00005681 E941E4FFFF          <1> 	jmp 	error   ; ... Printing procedure will be located here ...
  2791                              <1> 		;/	jsr	r0,cpass
  2792                              <1> 		;/	cmp	r0,$'a
  2793                              <1> 		;/	blo	1f
  2794                              <1> 		;/	cmp	r1,$'z
  2795                              <1> 		;/	bhi	1f
  2796                              <1> 		;/	sub	$40,r1
  2797                              <1> 		;/1:
  2798                              <1> 		;/	jsr	r0,lptoc
  2799                              <1> 		;/	br	wlpr
  2800                              <1> 		; br rmem / continue
  2801                              <1> 
  2802                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2803                              <1> 	; 17/10/2015
  2804                              <1> 	; 11/06/2015
  2805                              <1> 	; 24/05/2015
  2806                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2807                              <1> 	;
  2808 00005686 813D[10070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2808 0000568C [994F0000]          <1>
  2809 00005690 7415                <1>         je      short wmem_acc_err
  2810                              <1> 	;
  2811 00005692 8B35[5C6F0000]      <1>         mov     esi, [u.fofp] 
  2812                              <1> wmem_1:
  2813 00005698 E8BE000000          <1> 	call	cpass
  2814                              <1> 		; jsr r0,cpass / get next character from users area of
  2815                              <1> 			     ; / core and put it in r1
  2816                              <1>         	; mov r1,-(sp) / put character on the stack
  2817                              <1> 	; 20/09/2013
  2818 0000569D 74D0                <1> 	jz	short wret ; wmem_2  
  2819 0000569F 8B1E                <1>         mov     ebx, [esi]
  2820                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2821 000056A1 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2822                              <1> 		; inc *u.fofp / increment file offset to point to next
  2823                              <1> 			    ; / available location in file
  2824 000056A3 8803                <1> 	mov	[ebx], al	
  2825                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2826                              <1> 			        ; / assigned to it
  2827 000056A5 EBF1                <1> 	jmp	short wmem_1
  2828                              <1> 		; br wmem / continue
  2829                              <1> 	;1:
  2830                              <1> 	;jmp	error / ?
  2831                              <1> ;wmem_2:	
  2832                              <1> ;	; 20/09/2013
  2833                              <1> ;	pop	ax
  2834                              <1> ;	retn
  2835                              <1> 
  2836                              <1> wmem_acc_err:
  2837 000056A7 C705[A16F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2837 000056AF 0000                <1>
  2838 000056B1 E911E4FFFF          <1> 	jmp	error
  2839                              <1> 
  2840                              <1> 
  2841                              <1> dskw: ; / write routine for non-special files
  2842                              <1> 	;
  2843                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2844                              <1> 	; 25/07/2015
  2845                              <1> 	; 16/06/2015
  2846                              <1> 	; 09/06/2015
  2847                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2848                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2849                              <1> 	;
  2850                              <1> 	; 01/08/2013 (mkdir_w check)
  2851                              <1> 
  2852                              <1> 	;push	ax ; 26/04/2013
  2853                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  2854                              <1> 	; 24/12/2021
  2855 000056B6 50                  <1> 	push	eax
  2856                              <1> 	; AX = inode number
  2857 000056B7 E828FBFFFF          <1> 	call	iget
  2858                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2859                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2860 000056BC 8B1D[5C6F0000]      <1>         mov     ebx, [u.fofp] 
  2861 000056C2 8B13                <1> 	mov 	edx, [ebx]
  2862                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2863                              <1> 			       ; / in the fsp entry for this file] in r2
  2864 000056C4 0315[706F0000]      <1> 	add 	edx, [u.count]	
  2865                              <1> 		; add u.count,r2 / no. of bytes to be written
  2866                              <1> 			       ; / + file offset is put in r2
  2867                              <1> 	; 16/06/2015        
  2868 000056CA 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2869 000056D0 760F                <1> 	jna	short dskw_0
  2870 000056D2 C705[A16F0000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2870 000056DA 0000                <1>
  2871 000056DC E9E6E3FFFF          <1> 	jmp	error
  2872                              <1> dskw_0:	
  2873 000056E1 663B15[4C6C0000]    <1> 	cmp     dx, [i.size]
  2874                              <1> 		; cmp r2,i.size / is this greater than the present size of
  2875                              <1> 		              ; / the file?
  2876 000056E8 760C                <1> 	jna	short dskw_1
  2877                              <1> 		; blos 1f / no, branch
  2878 000056EA 668915[4C6C0000]    <1>         mov     [i.size], dx
  2879                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  2880                              <1> 			      ; / file offset + no. of data bytes
  2881 000056F1 E8F8FBFFFF          <1> 	call	setimod
  2882                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  2883                              <1> 		          ; / modified), stuff time of modification into
  2884                              <1> 	          	  ; / core image of i-node
  2885                              <1> dskw_1: ; 1:	
  2886 000056F6 E880F9FFFF          <1> 	call	mget
  2887                              <1> 	; eAX = Block number
  2888                              <1> 		; jsr r0,mget / get the block no. in which to write 
  2889                              <1> 			    ; /	the next data byte
  2890                              <1> 	; eax = block number
  2891 000056FB 8B1D[5C6F0000]      <1> 	mov     ebx, [u.fofp]
  2892 00005701 8B13                <1> 	mov	edx, [ebx]
  2893 00005703 81E2FF010000        <1> 	and	edx, 1FFh  
  2894                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  2895 00005709 750C                <1> 	jnz	short dskw_2
  2896                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  2897                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  2898 0000570B 813D[706F0000]0002- <1> 	cmp	dword [u.count], 512
  2898 00005713 0000                <1>
  2899                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  2900                              <1> 				  ; / an entire block? (i.e., no. of
  2901 00005715 7305                <1> 	jnb	short dskw_3
  2902                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  2903                              <1> 			; / Yes, branch. Don't have to read block
  2904                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  2905                              <1>    		; / overwritten).
  2906 00005717 E805060000          <1> 	call	dskrd
  2907                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  2908                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  2909                              <1> dskw_3: ; 3:
  2910                              <1> 	; eAX (r1) = block/sector number
  2911 0000571C E872060000          <1> 	call	wslot
  2912                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  2913                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  2914 00005721 803D[B36F0000]00    <1> 	cmp	byte [u.kcall], 0
  2915 00005728 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  2916                              <1> 	;
  2917 0000572A 66833D[B16F0000]00  <1> 	cmp	word [u.pcount], 0
  2918 00005732 7705                <1> 	ja	short dskw_5
  2919                              <1> dskw_4:
  2920                              <1> 	; [u.base] = virtual address to transfer (as source address)
  2921 00005734 E810FEFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2922                              <1> dskw_5:
  2923                              <1> 	; eBX (r5) = system (I/O) buffer address
  2924 00005739 E87D000000          <1> 	call	sioreg
  2925                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  2926                              <1> 			     ; / r1 = address of data, r2 points to location
  2927                              <1> 			     ; / in buffer in which to start writing data
  2928                              <1> 	; eSI = file (user data) offset
  2929                              <1> 	; eDI = sector (I/O) buffer offset
  2930                              <1> 	; eCX = byte count
  2931                              <1> 	;
  2932 0000573E F3A4                <1>   	rep	movsb
  2933                              <1> 		; movb (r1 )+,(r2)+ 
  2934                              <1> 		         ; / transfer a byte of data to the I/O buffer
  2935                              <1> 		; dec r3 / decrement no. of bytes to be written
  2936                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  2937                              <1> 	; 25/07/2015
  2938                              <1> 	; eax = remain bytes in buffer
  2939                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2940 00005740 09C0                <1> 	or	eax, eax
  2941 00005742 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  2942                              <1> dskw_6:
  2943 00005744 E866060000          <1> 	call	dskwr
  2944                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  2945 00005749 833D[706F0000]00    <1>         cmp     dword [u.count], 0
  2946                              <1> 		; tst u.count / any more data to write?
  2947 00005750 77A4                <1> 	ja	short dskw_1
  2948                              <1> 		; bne 1b / yes, branch
  2949                              <1> 	; 03/08/2013
  2950 00005752 C605[B36F0000]00    <1> 	mov	byte [u.kcall], 0
  2951                              <1> 	; 20/09/2013 (;;)
  2952                              <1> 	;pop	ax
  2953                              <1> 	; 24/12/2021
  2954 00005759 58                  <1> 	pop	eax
  2955 0000575A C3                  <1> 	retn
  2956                              <1> 	;;jmp 	short dskw_ret 
  2957                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  2958                              <1> 
  2959                              <1> cpass: ; / get next character from user area of core and put it in r1
  2960                              <1> 	; 18/10/2015
  2961                              <1> 	; 10/10/2015
  2962                              <1> 	; 10/07/2015
  2963                              <1> 	; 02/07/2015
  2964                              <1> 	; 01/07/2015
  2965                              <1> 	; 24/06/2015
  2966                              <1> 	; 08/06/2015
  2967                              <1> 	; 04/06/2015
  2968                              <1> 	; 20/05/2015
  2969                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2970                              <1> 	;
  2971                              <1> 	; INPUTS -> 
  2972                              <1> 	;     [u.base] = virtual address in user area
  2973                              <1> 	;     [u.count] = byte count (max.)
  2974                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  2975                              <1> 	; OUTPUTS -> 
  2976                              <1> 	;     AL = the character which is pointed by [u.base]
  2977                              <1> 	;     zf = 1 -> transfer count has been completed	
  2978                              <1>         ;
  2979                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  2980                              <1> 	;
  2981                              <1> 	;
  2982 0000575B 833D[706F0000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  2983                              <1> 		; tst u.count / have all the characters been transferred
  2984                              <1> 			    ; / (i.e., u.count, # of chars. left
  2985 00005762 763F                <1> 	jna	short cpass_3
  2986                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  2987 00005764 FF0D[706F0000]      <1> 	dec	dword [u.count]
  2988                              <1> 		; dec u.count / no, decrement u.count
  2989                              <1>         ; 19/05/2015 
  2990                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  2991                              <1> 	;		      to physical address
  2992 0000576A 66833D[B16F0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2993                              <1> 			     ; 1-4095 --> use previous physical base address
  2994                              <1> 			     ; in [u.pbase]
  2995 00005772 770E                <1> 	ja	short cpass_1
  2996                              <1> 	; 02/07/2015
  2997 00005774 833D[A96F0000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  2998 0000577B 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  2999                              <1> 	; 08/06/2015 - 10/07/2015
  3000 0000577D E8C7FDFFFF          <1> 	call	trans_addr_r
  3001                              <1> cpass_1:
  3002                              <1> 	; 02/07/2015
  3003                              <1> 	; 24/06/2015
  3004 00005782 66FF0D[B16F0000]    <1> 	dec	word [u.pcount]
  3005                              <1> cpass_2: 
  3006                              <1> 	; 10/10/2015
  3007                              <1> 	; 02/07/2015
  3008 00005789 8B15[AD6F0000]      <1> 	mov	edx, [u.pbase]
  3009 0000578F 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3010                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3011                              <1> 				; / by u.base and put it in r1
  3012 00005791 FF05[746F0000]      <1> 	inc	dword [u.nread]
  3013                              <1> 		; inc u.nread / increment no. of bytes transferred
  3014 00005797 FF05[6C6F0000]      <1> 	inc	dword [u.base]
  3015                              <1> 		; inc u.base / increment the buffer address to point to the
  3016                              <1> 			   ; / next byte
  3017 0000579D FF05[AD6F0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3018                              <1> cpass_3:
  3019 000057A3 C3                  <1> 	retn
  3020                              <1> 		; rts	r0 / next byte
  3021                              <1> 	; 1: 
  3022                              <1> 		; mov (sp)+,r0 
  3023                              <1> 		         ; / put return address of calling routine into r0
  3024                              <1> 		; mov (sp)+,r1 / i-number in r1
  3025                              <1> 		; rts r0 / non-local return
  3026                              <1> cpass_k:
  3027                              <1> 	; 02/07/2015
  3028                              <1> 	; The caller is os kernel 
  3029                              <1> 	; (get sysexec arguments from kernel's memory space)
  3030                              <1> 	;
  3031 000057A4 8B1D[6C6F0000]      <1> 	mov	ebx, [u.base]
  3032 000057AA 66C705[B16F0000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3032 000057B2 10                  <1>
  3033 000057B3 891D[AD6F0000]      <1> 	mov	[u.pbase], ebx
  3034 000057B9 EBCE                <1> 	jmp	short cpass_2
  3035                              <1> 	
  3036                              <1> sioreg: 
  3037                              <1> 	; 25/07/2015
  3038                              <1> 	; 18/07/2015
  3039                              <1> 	; 02/07/2015
  3040                              <1> 	; 17/06/2015
  3041                              <1> 	; 09/06/2015
  3042                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3043                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3044                              <1> 	;
  3045                              <1> 	; INPUTS -> 
  3046                              <1> 	;     eBX = system buffer (data) address (r5)
  3047                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3048                              <1> 	;     [u.base] = virtual address of the user buffer
  3049                              <1> 	;     [u.pbase] = physical address of the user buffer
  3050                              <1> 	;     [u.count] = byte count
  3051                              <1> 	;     [u.pcount] = byte count within page frame 			
  3052                              <1> 	; OUTPUTS -> 
  3053                              <1> 	;     eSI = user data offset (r1)
  3054                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  3055                              <1> 	;     eCX = byte count (r3)
  3056                              <1> 	;     EAX = remain bytes after byte count within page frame
  3057                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3058                              <1>         ;
  3059                              <1> 	; ((Modified registers:  EDX))
  3060                              <1>  
  3061 000057BB 8B35[5C6F0000]      <1>         mov     esi, [u.fofp]
  3062 000057C1 8B3E                <1>         mov     edi, [esi]
  3063                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3064 000057C3 89F9                <1> 	mov	ecx, edi
  3065                              <1> 		; mov r2,r3 / and also to r3
  3066 000057C5 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3067                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3068 000057CB 81E7FF010000        <1> 	and	edi, 1FFh
  3069                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3070 000057D1 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3071                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3072                              <1> 			  ; / where data is to be placed
  3073                              <1>                 ; mov u.base,r1 / address of data is in r1
  3074 000057D3 F7D9                <1> 	neg	ecx
  3075                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3076                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3077 000057D5 3B0D[706F0000]      <1> 	cmp	ecx, [u.count]
  3078                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3079                              <1> 			       ; / to be written to the file
  3080 000057DB 7606                <1> 	jna	short sioreg_0
  3081                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3082                              <1> 			 ; / in the file block as the number to be written
  3083 000057DD 8B0D[706F0000]      <1> 	mov	ecx, [u.count]
  3084                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3085                              <1> 			       ; / bytes as the number to be written
  3086                              <1> sioreg_0:
  3087                              <1> 	; 17/06/2015
  3088 000057E3 803D[B36F0000]00    <1> 	cmp	byte [u.kcall], 0 
  3089 000057EA 7613                <1> 	jna	short sioreg_1
  3090                              <1> 	; 25/07/2015
  3091                              <1> 	; the caller is 'mkdir' or 'namei'
  3092 000057EC A1[6C6F0000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3093 000057F1 A3[AD6F0000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3094 000057F6 66890D[B16F0000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3095 000057FD EB0B                <1> 	jmp	short sioreg_2
  3096                              <1> sioreg_1:
  3097                              <1> 	; 25/07/2015
  3098                              <1> 	; 18/07/2015
  3099                              <1> 	; 09/06/2015 
  3100 000057FF 0FB715[B16F0000]    <1> 	movzx	edx, word [u.pcount]
  3101                              <1> 		; ecx and [u.pcount] are always > 0, here
  3102 00005806 39D1                <1> 	cmp	ecx, edx	
  3103 00005808 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3104                              <1> sioreg_2: ; 2:
  3105 0000580A 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3106                              <1> sioreg_3:
  3107 0000580C 010D[746F0000]      <1> 	add 	[u.nread], ecx
  3108                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3109                              <1> 			         ; / during write is put into u.nread
  3110 00005812 290D[706F0000]      <1> 	sub 	[u.count], ecx
  3111                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3112                              <1> 			       ; / must be written or read
  3113 00005818 010D[6C6F0000]      <1> 	add 	[u.base], ecx
  3114                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3115                              <1> 			      ; / data bytes
  3116 0000581E 010E                <1>         add 	[esi], ecx 
  3117                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3118                              <1> 			       ; / + old file offset
  3119                              <1> 	; 25/07/2015
  3120 00005820 8B35[AD6F0000]      <1> 	mov	esi, [u.pbase]
  3121 00005826 66290D[B16F0000]    <1> 	sub	[u.pcount], cx
  3122 0000582D 010D[AD6F0000]      <1> 	add	[u.pbase], ecx
  3123 00005833 C3                  <1>         retn
  3124                              <1> 		; rts r0
  3125                              <1> 		; transfer count > [u.pcount]
  3126                              <1> sioreg_4:
  3127                              <1> 	; 25/07/2015
  3128                              <1> 	; transfer count > [u.pcount] 
  3129                              <1> 	; (ecx > edx)
  3130 00005834 89C8                <1> 	mov	eax, ecx
  3131 00005836 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3132 00005838 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3133 0000583A EBD0                <1> 	jmp	short sioreg_3
  2106                                  %include 'u7.s'        ; 18/04/2015
  2107                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYS7.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 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2119                              <1> ;
  2120                              <1> ; ****************************************************************************
  2121                              <1> 
  2122                              <1> sysmount: ; / mount file system; args special; name
  2123                              <1> 	; 15/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2124                              <1> 	; 09/02/2022
  2125                              <1> 	; 08/02/2022
  2126                              <1> 	; 07/02/2022
  2127                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2128                              <1> 	; 14/11/2015
  2129                              <1> 	; 24/10/2015
  2130                              <1> 	; 13/10/2015
  2131                              <1> 	; 10/07/2015
  2132                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2133                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2134                              <1> 	;
  2135                              <1> 	; 'sysmount' anounces to the system that a removable 
  2136                              <1> 	; file system has been mounted on a special file.
  2137                              <1> 	; The device number of the special file is obtained via
  2138                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2139                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2140                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2141                              <1> 	; to read file system into core, i.e. the first block on the
  2142                              <1> 	; mountable file system is read in. This block is super block
  2143                              <1> 	; for the file system. This call is super user restricted.	
  2144                              <1> 	;
  2145                              <1> 	; Calling sequence:
  2146                              <1> 	;	sysmount; special; name
  2147                              <1> 	; Arguments:
  2148                              <1> 	;	special - pointer to name of special file (device)
  2149                              <1> 	;	name -  pointer to name of the root directory of the
  2150                              <1> 	;		newly mounted file system. 'name' should 
  2151                              <1> 	;		always be a directory.
  2152                              <1> 	; Inputs: - 
  2153                              <1> 	; Outputs: -
  2154                              <1> 	; ...............................................................
  2155                              <1> 	;				
  2156                              <1> 	; Retro UNIX 8086 v1 modification: 
  2157                              <1> 	;       'sysmount' system call has two arguments; so,
  2158                              <1> 	;	* 1st argument, special is pointed to by BX register
  2159                              <1> 	;	* 2nd argument, name is in CX register
  2160                              <1> 	;
  2161                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2162                              <1> 	;	       already modified for IBM PC compatibility and 
  2163                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2164                              <1> 	
  2165                              <1> 	;call	arg2
  2166                              <1> 		; jsr r0,arg2 / get arguments special and name
  2167 0000583C 891D[646F0000]      <1> 	mov	[u.namep], ebx
  2168                              <1> 	; 09/02/2022
  2169                              <1> 	;push	ecx ; directory name
  2170 00005842 66833D[346F0000]00  <1> 	cmp	word [mnti], 0
  2171                              <1> 		; tst mnti / is the i-number of the cross device file
  2172                              <1> 			 ; / zero?
  2173                              <1> 	;;ja	error
  2174                              <1>         	; bne errora / no, error
  2175                              <1> 	;ja	sysmnt_err0
  2176                              <1> 	; 11/01/2022
  2177 0000584A 7605                <1> 	jna	short sysmnt_0
  2178 0000584C E968010000          <1> 	jmp	sysmnt_err0
  2179                              <1> sysmnt_0:
  2180                              <1> 	; 09/02/2022
  2181 00005851 51                  <1> 	push	ecx ; directory name
  2182 00005852 E84A010000          <1> 	call	getspl
  2183                              <1> 		; jsr r0,getspl / get special files device number in r1
  2184                              <1> 	; 09/02/2022
  2185 00005857 8F05[646F0000]      <1> 	pop	dword [u.namep] ; directory name
  2186                              <1> 	; 13/10/2015
  2187                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2188                              <1> 	; 11/01/2022
  2189 0000585D 29DB                <1> 	sub	ebx, ebx
  2190 0000585F 88C3                <1> 	mov	bl, al
  2191 00005861 F683[CA660000]80    <1> 	test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2192 00005868 750F                <1> 	jnz	short sysmnt_1
  2193                              <1> sysmnt_err1:
  2194 0000586A C705[A16F0000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2194 00005872 0000                <1>
  2195 00005874 E94EE2FFFF          <1> 	jmp	error
  2196                              <1> sysmnt_1:
  2197                              <1> 	; 09/02/2022
  2198                              <1> 	;pop	dword [u.namep]
  2199                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2200                              <1> 				  ; / on the device
  2201                              <1> 	; 14/11/2015
  2202 00005879 53                  <1> 	push	ebx ; 13/10/2015
  2203                              <1> 		; mov r1,-(sp) / save the device number
  2204                              <1>         ;
  2205 0000587A E855F1FFFF          <1> 	call	namei
  2206                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2207                              <1> 		       ; ax = 0 -> file not found 	
  2208                              <1> 	;jz	error
  2209                              <1> 	;jc	error
  2210                              <1> 		; jsr r0,namei / get the i-number of the file
  2211                              <1>                	; br errora
  2212 0000587F 730F                <1> 	jnc	short sysmnt_2
  2213                              <1> sysmnt_err2:
  2214 00005881 C705[A16F0000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2214 00005889 0000                <1>
  2215 0000588B E937E2FFFF          <1> 	jmp	error
  2216                              <1> sysmnt_2:	
  2217 00005890 66A3[346F0000]      <1> 	mov	[mnti], ax
  2218                              <1>         	; mov r1,mnti / put it in mnti
  2219                              <1> 
  2220                              <1> 	; 15/05/2022
  2221                              <1> 	; -Retro UNIX 8086/386 v1 feaure only-
  2222 00005896 66A1[2C6F0000]      <1> 	mov	ax, [ii]
  2223 0000589C 66A3[366F0000]      <1> 	mov	[mntp], ax ; parent dir inumber of [mnti]
  2224                              <1> 
  2225                              <1> 	; 11/01/2022
  2226 000058A2 BB[0C7E0000]        <1> 	mov	ebx, sb1 ; super block buffer header (of mounted disk)
  2227                              <1> sysmnt_3: ;1:
  2228                              <1>         ;cmp	byte [ebx+1], 0
  2229                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2230                              <1> 			   ; / dismountable device set?
  2231                              <1>         ;jna	short sysmnt_4		
  2232                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2233                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2234                              <1> 	;jmp	short sysmnt_3
  2235                              <1> sysmnt_4:   
  2236 000058A7 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2237 000058A8 A2[316F0000]        <1> 	mov	[mdev], al
  2238                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2239 000058AD 8803                <1> 	mov	[ebx], al
  2240                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2241                              <1> 			      ; / of the I/O queue entry
  2242                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2243                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2244 000058AF 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2245                              <1> 		; bis $2000,sb1 / set the read bit
  2246                              <1> 	; Retro UNIX 386 v1 modification : 
  2247                              <1> 	;	32 bit block number at buffer header offset 4
  2248 000058B4 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2249 000058BB E83A060000          <1> 	call 	diskio
  2250 000058C0 7345                <1> 	jnc	short sysmnt_5
  2251 000058C2 31C0                <1> 	xor 	eax, eax
  2252 000058C4 66A3[346F0000]      <1> 	mov	[mnti], ax ; 0
  2253 000058CA A2[316F0000]        <1> 	mov	[mdev], al ; 0
  2254                              <1> 	;mov	[cdev], al ; 0
  2255                              <1> 	; 08/02/2022
  2256 000058CF 803D[B46F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2257 000058D6 7508                <1> 	jne	short sysmnt_err3
  2258                              <1> 	; yes, clear [u.brwdev] for next check
  2259                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2260 000058D8 FE05[B46F0000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2261 000058DE EB0A                <1> 	jmp	short sysmnt_err4
  2262                              <1> sysmnt_err3:	; 08/02/2022
  2263                              <1> 	; no, set [u.error] to disk read error
  2264 000058E0 C705[A16F0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2264 000058E8 0000                <1>
  2265                              <1> sysmnt_err4:
  2266                              <1> 	; 08/02/2022
  2267                              <1> 	; 14/11/2015
  2268 000058EA FEC8                <1> 	dec 	al
  2269 000058EC 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2270 000058EE FEC0                <1> 	inc	al
  2271 000058F0 48                  <1> 	dec	eax
  2272 000058F1 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2273 000058F4 E9CEE1FFFF          <1> 	jmp	error
  2274                              <1> sysmnt_invd:
  2275                              <1> 	; 08/02/2022
  2276 000058F9 C705[A16F0000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2276 00005901 0000                <1>
  2277                              <1> 				 ;'invalid fs/superblock !' error
  2278 00005903 30C0                <1> 	xor	al, al
  2279 00005905 EBE3                <1> 	jmp	short sysmnt_err4	
  2280                              <1> 
  2281                              <1> sysmnt_5:
  2282                              <1> 	; 08/02/2022
  2283                              <1> 	; 11/01/2022 (BugFix)
  2284                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2285                              <1> 	; (Following check is needed to prevent mounting an
  2286                              <1> 	; invalid file system (invalid super block).
  2287                              <1> 	; 
  2288 00005907 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2289 0000590A C0E002              <1> 	shl	al, 2 ; 4*index
  2290 0000590D 8B88[AE660000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2291 00005913 C1E903              <1> 	shr 	ecx, 3 ; 11/01/2021 (8 sectors per 1 fbm byte)
  2292                              <1> 	; ecx = number of free map bytes (required)
  2293                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2294 00005916 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)	
  2295                              <1> 	; edx = number of free blocks map bytes
  2296                              <1> 	;shl	edx, 3 ; convert free map bytes to free map bits
  2297                              <1> 	; 07/02/2022
  2298                              <1> 	;xor	al, al ; 08/02/2022
  2299 0000591A 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2300                              <1> 			 ; (in sectors), if they are not equal
  2301                              <1> 			 ; the disk to be mounted is an...	
  2302 0000591C 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2303                              <1> 			 ; (which has not got a valid super block)
  2304                              <1> 	;
  2305 0000591E C6430100            <1> 	mov	byte [ebx+1], 0
  2306                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2307                              <1> ;sysmnt_6: ;1:
  2308                              <1> 	;;cmp	byte [sb1+1], 0
  2309                              <1> 		; tstb sb1+1 / done reading?
  2310                              <1>    	;;jna	sysret
  2311                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2312                              <1> 	;;jmp	short sysmnt_6
  2313                              <1> 		; bne 1b / no, wait
  2314                              <1>         	; br sysreta / yes
  2315 00005922 E9C0E1FFFF          <1> 	jmp	sysret
  2316                              <1> 
  2317                              <1> sysumount: ; / special dismount file system
  2318                              <1> 	; 15/05/2022
  2319                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2320                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2321                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2322                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2323                              <1> 	;
  2324                              <1> 	; 04/11/2013
  2325                              <1> 	; 09/07/2013
  2326                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2327                              <1> 	; indicated as an argument is no longer contain a removable
  2328                              <1> 	; file system. 'getspl' gets the device number of the special
  2329                              <1> 	; file. If no file system was mounted on that device an error
  2330                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2331                              <1> 	; to 'sysret'.
  2332                              <1> 	;
  2333                              <1> 	; Calling sequence:
  2334                              <1> 	;	sysmount; special
  2335                              <1> 	; Arguments:
  2336                              <1> 	;	special - special file to dismount (device)
  2337                              <1> 	;
  2338                              <1> 	; Inputs: - 
  2339                              <1> 	; Outputs: -
  2340                              <1> 	; ...............................................................
  2341                              <1> 	;				
  2342                              <1> 	; Retro UNIX 8086 v1 modification: 
  2343                              <1> 	;       'sysumount' system call has one argument; so,
  2344                              <1> 	;	* Single argument, special is pointed to by BX register
  2345                              <1> 	;
  2346                              <1> 	
  2347                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2348                              <1> 	;call	arg
  2349                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2350 00005927 891D[646F0000]      <1>         mov	[u.namep], ebx
  2351 0000592D E86F000000          <1> 	call	getspl
  2352                              <1> 		; jsr r0,getspl / get the device number in r1
  2353                              <1> 
  2354                              <1> 	;;;
  2355                              <1> 	; 09/05/2022 - Erdogan Tan
  2356                              <1> 	; (I have added [mnti] check because
  2357                              <1> 	;  retro unix device number of /dev/fd0 is 0
  2358                              <1> 	;  .. so, 'cmp al, [mdev]' is not enough
  2359                              <1> 	;  for dismounting /dev/fd0. sysumount system call would give
  2360                              <1> 	;  wrong cf=0 result while /dev/fd0 is not mounted.)
  2361 00005932 66833D[346F0000]00  <1> 	cmp	word [mnti], 0
  2362 0000593A 767D                <1> 	jna	short sysmnt_err0 ; there is not a mounted device !
  2363                              <1> 	;;;
  2364                              <1> 
  2365 0000593C 3A05[316F0000]      <1> 	cmp	al, [mdev]
  2366                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2367 00005942 7575                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2368                              <1> 	;jne	error
  2369                              <1>         	; bne errora / no error
  2370 00005944 30C0                <1> 	xor	al, al ; ah = 0
  2371                              <1> sysumnt_0: ;1:
  2372                              <1>      	; 11/01/2022
  2373                              <1> 	;cmp 	[sb1+1], al ; 0
  2374                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2375                              <1> 	;		   ; / (inhibit bit set)?
  2376                              <1> 	;jna	short sysumnt_1		
  2377                              <1> 	;	; bne 1b / yes, wait
  2378                              <1> 	;call	idle ; (wait for hardware interrupt)
  2379                              <1> 	;jmp	short sysumnt_0
  2380                              <1> sysumnt_1:        
  2381                              <1> 	; 15/05/2022
  2382                              <1> 	; change user's current directory to mounting directory
  2383                              <1> 	; if it is on the mounted device (chdir back to root fs)
  2384 00005946 3805[966F0000]      <1> 	cmp	byte [u.cdrv], al ; 0
  2385 0000594C 7643                <1> 	jna	short sysumnt_4
  2386                              <1> 	;;;
  2387                              <1> 	; 15/05/2022
  2388                              <1> 	; It is needed to change the parent process's current
  2389                              <1> 	; directory because shell runs (/etc/umount) 
  2390                              <1> 	; as child process.
  2391 0000594E 31DB                <1> 	xor	ebx, ebx 
  2392 00005950 8A1D[9B6F0000]      <1> 	mov	bl, [u.uno]
  2393 00005956 D0E3                <1> 	shl	bl, 1 ; >= 2 .. <= 32
  2394 00005958 81C3[866C0000]      <1> 	add	ebx, p.ppid-2
  2395 0000595E 668B13              <1> 	mov	dx, [ebx] ; process id of the parent [p.ppid]	
  2396 00005961 BE[686C0000]        <1> 	mov	esi, p.pid
  2397 00005966 29C9                <1> 	sub	ecx, ecx
  2398 00005968 B110                <1> 	mov	cl, nproc ; 16  
  2399                              <1> sysumnt_2:	
  2400 0000596A 66AD                <1> 	lodsw
  2401 0000596C 6639D0              <1> 	cmp	ax, dx
  2402 0000596F 7402                <1> 	je	short sysumnt_3
  2403 00005971 E2F7                <1> 	loop	sysumnt_2
  2404                              <1> sysumnt_3:
  2405 00005973 31C0                <1> 	xor	eax, eax
  2406 00005975 81EE[686C0000]      <1> 	sub	esi, p.pid
  2407 0000597B D1E6                <1> 	shl	esi, 1
  2408 0000597D 8B9E[D46C0000]      <1> 	mov	ebx, [esi+p.upage-4] ; the parent's upage
  2409                              <1> 	; ebx points to user (u) structure in upage
  2410 00005983 668B15[346F0000]    <1> 	mov	dx, [mnti]
  2411                              <1> 	;mov	[u.cdir], dx
  2412                              <1> 	;mov	[u.cdrv], al ; 0
  2413 0000598A 6689530C            <1> 	mov	[ebx+u.cdir-user], dx
  2414 0000598E 884352              <1> 	mov	[ebx+u.cdrv-user], al ; 0
  2415                              <1> 	;;;
  2416                              <1> sysumnt_4: 
  2417 00005991 A2[316F0000]        <1> 	mov	[mdev], al ; 0
  2418                              <1> 	     	; clr mntd / no, clear these
  2419 00005996 66A3[346F0000]      <1>    	mov	[mnti], ax ; 0
  2420                              <1>         	; clr mnti
  2421                              <1> 
  2422                              <1> 	;; 15/05/2022
  2423                              <1> 	;mov	[cdev], al ; 0 ; [u.cdrv] = 0
  2424                              <1> 	;mov	ax, dx  ; [u.cdir]
  2425                              <1> 	;call	iget
  2426                              <1> 
  2427 0000599C E946E1FFFF          <1>         jmp	sysret
  2428                              <1> 		; br sysreta / return
  2429                              <1> 
  2430                              <1> getspl: ; / get device number from a special file name
  2431 000059A1 E82EF0FFFF          <1> 	call	namei
  2432                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2433                              <1> 		       ; ax = 0 -> file not found 	
  2434                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2435                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2436 000059A6 7305                <1> 	jnc	short getspl_0
  2437 000059A8 E9D4FEFFFF          <1> 	jmp	sysmnt_err2 ; 'file not found !' error
  2438                              <1> getspl_0:
  2439                              <1> 	;jz	error
  2440                              <1> 	;jc	error
  2441                              <1> 		; jsr r0,namei / get the i-number of the special file
  2442                              <1>                 ; br errora / no such file
  2443 000059AD 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2444                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2445                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2446 000059B1 7206                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2447                              <1> 	;jc	error
  2448                              <1> 		; ble errora / less than 0?  yes, error
  2449 000059B3 6683F805            <1>         cmp	ax, 5 ;
  2450                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2451                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2452                              <1> 	;;ja	error
  2453                              <1> 		; bgt errora / yes, error
  2454                              <1> 	; 11/01/2022
  2455 000059B7 760F                <1> 	jna	short getspl_retn
  2456                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2457                              <1> ;iopen_retn:
  2458                              <1> ;	retn
  2459                              <1> 		; rts r0 / return with device number in r1
  2460                              <1> sysmnt_err0:
  2461 000059B9 C705[A16F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2461 000059C1 0000                <1>
  2462 000059C3 E9FFE0FFFF          <1> 	jmp	error
  2463                              <1> 
  2464                              <1> getspl_retn:
  2465                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2466                              <1> 	; 11/01/2022
  2467                              <1> iopen_retn:
  2468 000059C8 C3                  <1> 	retn
  2469                              <1> 
  2470                              <1> iopen:
  2471                              <1> 	; 11/01/2022
  2472                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2473                              <1> 	; 19/05/2015
  2474                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2475                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2476                              <1> 	;
  2477                              <1> 	; open file whose i-number is in r1
  2478                              <1> 	; 
  2479                              <1> 	; INPUTS ->
  2480                              <1> 	;    r1 - inode number
  2481                              <1> 	; OUTPUTS ->
  2482                              <1> 	;    file's inode in core	
  2483                              <1> 	;    r1 - inode number (positive)
  2484                              <1> 	;
  2485                              <1> 	; ((AX = R1))
  2486                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2487                              <1> 	;        
  2488                              <1> ; / open file whose i-number is in r1
  2489 000059C9 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2490                              <1> 		; tst r1 / write or read access?
  2491 000059CC 7568                <1>         jnz	short iopen_2
  2492                              <1> 		; blt 2f / write, go to 2f
  2493 000059CE B202                <1> 	mov	dl, 2 ; read access
  2494 000059D0 E8E3F8FFFF          <1> 	call	access
  2495                              <1>         	; jsr r0,access; 2 
  2496                              <1> 	; / get inode into core with read access
  2497                              <1> 	; DL=2
  2498                              <1> iopen_0:
  2499 000059D5 6683F828            <1>         cmp	ax, 40
  2500                              <1> 		; cmp r1,$40. / is it a special file
  2501 000059D9 77ED                <1>         ja	short iopen_retn
  2502                              <1> 		; bgt  3f / no. 3f
  2503 000059DB 50                  <1> 	push	eax ; 08/01/2022
  2504                              <1> 	;push	ax
  2505                              <1> 		; mov r1,-(sp) / yes, figure out
  2506 000059DC 0FB6D8              <1> 	movzx	ebx, al
  2507 000059DF C0E302              <1> 	shl	bl, 2 ; * 4 ; 08/01/2022
  2508                              <1> 	;shl	bx, 2
  2509                              <1> 		; asl r1
  2510 000059E2 81C3[E6590000]      <1>         add     ebx, iopen_1 - 4
  2511 000059E8 FF23                <1> 	jmp	dword [ebx]
  2512                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2513                              <1> iopen_1: ; 1:
  2514 000059EA [4E5A0000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2515                              <1>  		 ;otty / tty ; r1=2
  2516                              <1>         	 ;oppt / ppt ; r1=4
  2517 000059EE [065B0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2518                              <1> 		 ;sret / mem ; r1=6
  2519                              <1> 		 ;sret / rf0
  2520                              <1>         	 ;sret / rk0
  2521                              <1>         	 ;sret / tap0
  2522                              <1>         	 ;sret / tap1
  2523                              <1>         	 ;sret / tap2
  2524                              <1>         	 ;sret / tap3
  2525                              <1>         	 ;sret / tap4
  2526                              <1>         	 ;sret / tap5
  2527                              <1>         	 ;sret / tap6
  2528                              <1>         	 ;sret / tap7
  2529 000059F2 [065B0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2530 000059F6 [065B0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2531 000059FA [065B0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2532 000059FE [065B0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2533 00005A02 [065B0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2534 00005A06 [065B0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2535                              <1> 	;dd	error ; lpr, AX = 9 (error !)
  2536 00005A0A [065B0000]          <1>         dd      sret ; lpr, AX = 9 (runix)
  2537 00005A0E [5F5A0000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2538                              <1> 		 ;ocvt / tty0
  2539 00005A12 [5F5A0000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2540                              <1> 		 ;ocvt / tty1
  2541 00005A16 [5F5A0000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2542                              <1> 		 ;ocvt / tty2
  2543 00005A1A [5F5A0000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2544                              <1> 		 ;ocvt / tty3
  2545 00005A1E [5F5A0000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2546                              <1> 		 ;ocvt / tty4
  2547 00005A22 [5F5A0000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2548                              <1> 		 ;ocvt / tty5
  2549 00005A26 [5F5A0000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2550                              <1> 		 ;ocvt / tty6
  2551 00005A2A [5F5A0000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2552                              <1> 		 ;ocvt / tty7
  2553 00005A2E [5F5A0000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2554                              <1> 		 ;error / crd
  2555 00005A32 [5F5A0000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2556                              <1> 
  2557                              <1> iopen_2: ; 2: / check open write access
  2558 00005A36 66F7D8              <1> 	neg	ax
  2559                              <1> 		;neg r1 / make inode number positive
  2560 00005A39 B201                <1> 	mov	dl, 1 ; write access
  2561 00005A3B E878F8FFFF          <1> 	call	access
  2562                              <1> 		;jsr r0,access; 1 / get inode in core
  2563                              <1> 	; DL=1
  2564                              <1> 	; 11/01/2022
  2565 00005A40 F605[496C0000]40    <1> 	test	byte [i.flgs+1], 40h
  2566                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2567                              <1>  		; bit $40000,i.flgs / is it a directory?
  2568 00005A47 748C                <1> 	jz	short iopen_0
  2569                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2570                              <1> 	;jmp	error ; permission denied !
  2571 00005A49 E96BFFFFFF          <1> 	jmp	sysmnt_err0
  2572                              <1> 	;;jnz	error		
  2573                              <1>        		; bne 2f / yes, transfer (error)
  2574                              <1>         ;;jmp	short iopen_0
  2575                              <1> 	;cmp	ax, 40
  2576                              <1> 		; cmp r1,$40. / no, is it a special file?
  2577                              <1>         ;ja	short iopen_2
  2578                              <1> 		; bgt 3f / no, return
  2579                              <1> 	;push	ax
  2580                              <1> 		; mov r1,-(sp) / yes
  2581                              <1> 	;movzx	ebx, al
  2582                              <1> 	;shl	bx, 1
  2583                              <1> 		; asl r1
  2584                              <1> 	;add	ebx, ipen_3 - 2
  2585                              <1> 	;jmp	dword [ebx]
  2586                              <1> 		; jmp *1f-2(r1) / figure out 
  2587                              <1> 			; / which special file it is and transfer
  2588                              <1> ;iopen_3: ; 1:
  2589                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2590                              <1>  		 ;otty / tty ; r1=2
  2591                              <1>         	 ;leadr / ppt ; r1=4
  2592                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2593                              <1> 		 ;sret / mem ; r1=6
  2594                              <1> 		 ;sret / rf0
  2595                              <1>         	 ;sret / rk0
  2596                              <1>         	 ;sret / tap0
  2597                              <1>         	 ;sret / tap1
  2598                              <1>         	 ;sret / tap2
  2599                              <1>         	 ;sret / tap3
  2600                              <1>         	 ;sret / tap4
  2601                              <1>         	 ;sret / tap5
  2602                              <1>         	 ;sret / tap6
  2603                              <1>         	 ;sret / tap7
  2604                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2605                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2606                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2607                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2608                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2609                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2610                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2611                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2612                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2613                              <1> 		 ;ocvt / tty0
  2614                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2615                              <1> 		 ;ocvt / tty1
  2616                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2617                              <1> 		 ;ocvt / tty2
  2618                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2619                              <1> 		 ;ocvt / tty3
  2620                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2621                              <1> 		 ;ocvt / tty4
  2622                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2623                              <1> 		 ;ocvt / tty5
  2624                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2625                              <1> 		 ;ocvt / tty6
  2626                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2627                              <1> 		 ;ocvt / tty7
  2628                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2629                              <1> 		 ;/ ejec / lpr
  2630                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2631                              <1> 
  2632                              <1> otty: ;/ open console tty for reading or writing
  2633                              <1> 	; 03/03/2022
  2634                              <1> 	; 02/03/2022
  2635                              <1> 	; 26/02/2022
  2636                              <1> 	; 09/02/2022
  2637                              <1> 	; 06/02/2022
  2638                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2639                              <1> 	; 16/11/2015
  2640                              <1> 	; 12/11/2015
  2641                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2642                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2643                              <1> 	; 16/07/2013
  2644                              <1> 	; Retro UNIX 8086 v1 modification:
  2645                              <1> 	;  If a tty is open for read or write by
  2646                              <1> 	;     a process (u.uno), only same process can open
  2647                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2648                              <1> 	;
  2649                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2650                              <1> 	;
  2651 00005A4E 0FB61D[9B6F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2652 00005A55 8A83[A76C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2653                              <1> 	; 13/01/2014
  2654                              <1> 	;jmp	short ottyp
  2655                              <1> 	; 26/02/2022
  2656 00005A5B 88C4                <1> 	mov	ah, al
  2657 00005A5D EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2658                              <1> ocvt:
  2659 00005A5F 2C0A                <1> 	sub	al, 10
  2660                              <1> ;ottyp:	; (call from sysstty)
  2661                              <1> 	; 08/01/2022
  2662 00005A61 31DB                <1> 	xor	ebx, ebx
  2663                              <1> ottyp:	; (ebx < 256) ; 06/02/2022
  2664                              <1> 	; 26/02/2022
  2665 00005A63 B4FF                <1> 	mov	ah, 0FFh
  2666                              <1> ottypc:
  2667                              <1> 	; 03/03/2022
  2668                              <1> 	; 26/02/2022
  2669                              <1> 	; 09/02/2022
  2670                              <1> 	; 08/01/2022
  2671                              <1> 	; 16/11/2015
  2672                              <1> 	; 12/11/2015
  2673                              <1> 	; 18/05/2015 (32 bit modifications)
  2674                              <1> 	; 06/12/2013 - 13/07/2014
  2675 00005A65 88C6                <1> 	mov	dh, al ; tty number
  2676                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2677                              <1> 	; 08/01/2022
  2678 00005A67 88C3                <1> 	mov	bl, al
  2679 00005A69 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2680                              <1> 	; 26/01/2014	
  2681 00005A6B 81C3[D46B0000]      <1> 	add 	ebx, ttyl
  2682 00005A71 668B0B              <1> 	mov 	cx, [ebx]
  2683                              <1> 		   ; CL = lock value (0 or process number)
  2684                              <1> 		   ; CH = open count 
  2685 00005A74 20C9                <1> 	and 	cl, cl
  2686                              <1> 	; 13/01/2014
  2687                              <1> 	;jz 	short otty_ret
  2688                              <1> 	; 08/01/2022
  2689 00005A76 7447                <1> 	jz 	short ottys_0
  2690                              <1> 	;
  2691                              <1> 	; 16/11/2015
  2692 00005A78 3A0D[9B6F0000]      <1> 	cmp 	cl, [u.uno]
  2693 00005A7E 746E                <1> 	je	short ottys_3
  2694                              <1> 	;
  2695                              <1> 	;
  2696                              <1> 	; 26/02/2022
  2697                              <1> 	; (is it the console tty of the current process?)
  2698                              <1> 	; ((fast check/permit for console tty open function))
  2699 00005A80 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2700 00005A82 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2701                              <1> 	;
  2702                              <1> 	; 26/02/2022
  2703                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2704                              <1> 	;shl 	bl, 1
  2705                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2706                              <1> 	;;movzx ebx, byte [u.uno]
  2707                              <1> 	;mov	bl, [u.uno]
  2708                              <1> 	;shl 	bl, 1
  2709                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2710                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2711                              <1> 	; 26/02/2022 (BugFix) ; *
  2712 00005A84 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2713 00005A87 D1E6                <1> 	shl 	esi, 1
  2714 00005A89 668B86[666C0000]    <1> 	mov 	ax, [esi+p.pid-2]
  2715 00005A90 96                  <1> 	xchg	esi, eax
  2716 00005A91 A0[9B6F0000]        <1> 	mov	al, [u.uno]
  2717 00005A96 D0E0                <1> 	shl 	al, 1
  2718 00005A98 663BB0[866C0000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2719 00005A9F 744D                <1> 	je 	short ottys_3 ; *
  2720                              <1> 	; 26/02/2022
  2721                              <1> 	; check console tty of the process
  2722                              <1> 	; (open permission must be given if the -requested- tty is
  2723                              <1> 	;  console tty of current process)
  2724 00005AA1 D0E8                <1> 	shr	al, 1
  2725 00005AA3 38B0[A76C0000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2726 00005AA9 7443                <1> 	je 	short ottys_3
  2727                              <1> 	;
  2728                              <1> 	; the tty is locked by another process
  2729                              <1> 	; except the parent process (p.ppid)
  2730                              <1>         ;
  2731                              <1> 	; 09/02/2022
  2732                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2733                              <1> 	;		; permission denied ! error
  2734                              <1> otty_err: ; 13/01/2014
  2735                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2736                              <1> 	;;jnz	error
  2737                              <1> 	; 05/12/2021
  2738                              <1> 	;jz	short otty_stc_retn
  2739                              <1> 	;jmp	error
  2740                              <1> 	; 09/02/2022
  2741 00005AAB 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2742 00005AAE 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2743                              <1> 	; iopen (dl=1 or dl=2)
  2744 00005AB0 C705[A16F0000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2744 00005AB8 0000                <1>
  2745                              <1> 			; permission denied ! error
  2746 00005ABA E908E0FFFF          <1> 	jmp	error
  2747                              <1> ;otty_stc_retn:
  2748                              <1> 	;stc
  2749                              <1> 	;retn
  2750                              <1> ottys_0:
  2751                              <1> 	; 08/01/2022
  2752                              <1> otty_ret: 
  2753                              <1> 	; 13/01/2014
  2754 00005ABF 80FE07              <1> 	cmp 	dh, 7
  2755 00005AC2 7624                <1> 	jna	short ottys_2
  2756                              <1> 	; 16/11/2015
  2757                              <1> com_port_check:
  2758 00005AC4 BE[F26B0000]        <1> 	mov	esi, com1p
  2759 00005AC9 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2760 00005ACC 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2761 00005ACE 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2762                              <1> ottys_1:
  2763                              <1> 	; 12/11/2015
  2764 00005ACF 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2765 00005AD2 7714                <1> 	ja	short com_port_ready
  2766                              <1> 	;
  2767                              <1> 	; 09/02/2022
  2768 00005AD4 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2769 00005AD7 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2770 00005AD9 C705[A16F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2770 00005AE1 0000                <1>
  2771                              <1> 			   ; device not ready ! error
  2772                              <1> 	;jmp	short otty_err
  2773 00005AE3 E9DFDFFFFF          <1> 	jmp	error
  2774                              <1> com_port_ready:
  2775                              <1> ottys_2:
  2776                              <1> 	; 02/03/2022
  2777                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2778                              <1> 	;jnz	short ottys_3
  2779 00005AE8 8A0D[9B6F0000]      <1> 	mov	cl, [u.uno]
  2780                              <1> ottys_3:
  2781 00005AEE FEC5                <1> 	inc 	ch
  2782 00005AF0 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2783                              <1> 	; 06/12/2013
  2784 00005AF3 FEC6                <1> 	inc	dh ; tty number + 1
  2785 00005AF5 BB[7C6F0000]        <1> 	mov	ebx, u.ttyp
  2786                              <1> 	; 13/01/2014
  2787 00005AFA F6C202              <1> 	test	dl, 2 ; open for read sign
  2788 00005AFD 7501                <1> 	jnz	short ottys_4
  2789 00005AFF 43                  <1> 	inc	ebx
  2790                              <1> ottys_4:
  2791                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2792 00005B00 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2793                              <1> 	; 09/02/2022
  2794 00005B02 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2795 00005B04 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2796                              <1> sret:
  2797                              <1> 	;pop 	ax
  2798 00005B06 58                  <1> 	pop	eax ; 08/01/2022
  2799                              <1> otty_retn:	; 09/02/2022
  2800                              <1> iclose_retn:	
  2801 00005B07 C3                  <1> 	retn
  2802                              <1> 
  2803                              <1> 	;
  2804                              <1> 	; Original UNIX v1 'otty' routine:
  2805                              <1> 	;	
  2806                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2807                              <1>         ;                 / reader status reg
  2808                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2809                              <1>         ;                 / punch status reg
  2810                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2811                              <1>         ;                          / console tty buffer
  2812                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2813                              <1>         ;            / console tty
  2814                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2815                              <1>         ;             / buffer header
  2816                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2817                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2818                              <1>         ;                 / tty
  2819                              <1>         ;br     sret / ?
  2820                              <1> ;sret:
  2821                              <1> 		;clr *$ps / set processor priority to zero
  2822                              <1> ;	pop	ax
  2823                              <1>         	;mov (sp)+,r1 / pop stack to r1
  2824                              <1> ;3:
  2825                              <1> ;	retn
  2826                              <1>         	;rts r0
  2827                              <1> 	
  2828                              <1> ;ocvt:	; < open tty >
  2829                              <1> 	; 13/01/2014
  2830                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2831                              <1> 	; 24/09/2013 consistency check -> ok
  2832                              <1> 	; 16/09/2013
  2833                              <1> 	; 03/09/2013
  2834                              <1> 	; 27/08/2013
  2835                              <1> 	; 16/08/2013
  2836                              <1> 	; 16/07/2013
  2837                              <1> 	; 27/05/2013
  2838                              <1> 	; 21/05/2013
  2839                              <1> 	;
  2840                              <1> 	; Retro UNIX 8086 v1 modification !
  2841                              <1> 	; 
  2842                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2843                              <1> 	;	(exactly different than this one)
  2844                              <1> 	;	was in 'u9.s' file.
  2845                              <1> 	;
  2846                              <1> 	; 16/07/2013
  2847                              <1> 	; Retro UNIX 8086 v1 modification:
  2848                              <1> 	;  If a tty is open for read or write by
  2849                              <1> 	;     a process (u.uno), only same process can open
  2850                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2851                              <1> 	;
  2852                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2853                              <1> 
  2854                              <1> 	; 16/09/2013
  2855                              <1> 	; sub 	al, 10
  2856                              <1> 	
  2857                              <1> 	; 06/12/2013
  2858                              <1> 	;cmp	al, 7
  2859                              <1>         ;jna     short ottyp
  2860                              <1> 	; 13/01/2014
  2861                              <1> 	;jmp	short ottyp
  2862                              <1> 
  2863                              <1> ;oppt: / open paper tape for reading or writing
  2864                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2865                              <1> ;        tstb   pptiflg / is file already open
  2866                              <1> ;        bne    2f / yes, branch
  2867                              <1> ;1:
  2868                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2869                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2870                              <1> ;               br .+4 / for paper tape input and place in free list
  2871                              <1> ;        br     1b
  2872                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2873                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2874                              <1> ;        br     sret
  2875                              <1> ;2:
  2876                              <1> ;        jmp    error / file already open
  2877                              <1> 
  2878                              <1> iclose:
  2879                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2880                              <1> 	; 19/05/2015
  2881                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2882                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2883                              <1> 	;
  2884                              <1> 	; close file whose i-number is in r1
  2885                              <1> 	; 
  2886                              <1> 	; INPUTS ->
  2887                              <1> 	;    r1 - inode number
  2888                              <1> 	; OUTPUTS ->
  2889                              <1> 	;    file's inode in core	
  2890                              <1> 	;    r1 - inode number (positive)
  2891                              <1> 	;
  2892                              <1> 	; ((AX = R1))
  2893                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2894                              <1> 	;        
  2895                              <1> ;/ close file whose i-number is in r1
  2896 00005B08 B202                <1> 	mov	dl, 2 ; 12/01/2014
  2897 00005B0A F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2898                              <1> 		; tst r1 / test i-number
  2899                              <1>         ;jnz	short iclose_2
  2900                              <1> 		; blt 2f / if neg., branch
  2901 00005B0D 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2902                              <1> 	; 16/07/2013 
  2903 00005B0F 66F7D8              <1> 	neg	ax ; make it positive
  2904                              <1> 	; 12/01/2014
  2905 00005B12 FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2906                              <1> iclose_0:
  2907 00005B14 6683F828            <1> 	cmp	ax, 40
  2908                              <1> 		; cmp r1,$40. / is it a special file
  2909 00005B18 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2910                              <1> 		; bgt 3b / no, return
  2911                              <1> 	; 12/01/2014
  2912                              <1> 	; DL=2 -> special file was opened for reading
  2913                              <1> 	; DL=1 -> special file was opened for writing
  2914 00005B1A 50                  <1> 	push	eax ; 08/01/2022
  2915                              <1> 	;push	ax
  2916                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2917 00005B1B 0FB6D8              <1> 	movzx	ebx, al
  2918                              <1> 	; 08/01/2022
  2919 00005B1E C0E302              <1> 	shl	bl, 2
  2920                              <1> 	;shl	bx, 2
  2921                              <1> 		; asl r1
  2922 00005B21 81C3[255B0000]      <1> 	add	ebx, iclose_1 - 4
  2923 00005B27 FF23                <1> 	jmp	dword [ebx]
  2924                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2925                              <1> iclose_1 :
  2926 00005B29 [755B0000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2927 00005B2D [D05B0000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2928 00005B31 [D05B0000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2929 00005B35 [D05B0000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2930 00005B39 [D05B0000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2931 00005B3D [D05B0000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2932 00005B41 [D05B0000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2933 00005B45 [D05B0000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2934 00005B49 [D05B0000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2935                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2936                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2937 00005B4D [845B0000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2938 00005B51 [845B0000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2939 00005B55 [845B0000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2940 00005B59 [845B0000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2941 00005B5D [845B0000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2942 00005B61 [845B0000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2943 00005B65 [845B0000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2944 00005B69 [845B0000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2945 00005B6D [845B0000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2946 00005B71 [845B0000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2947                              <1> 
  2948                              <1> 	; 1:
  2949                              <1> 	;        ctty   / tty
  2950                              <1> 	;        cppt   / ppt
  2951                              <1> 	;        sret   / mem
  2952                              <1> 	;        sret   / rf0
  2953                              <1> 	;        sret   / rk0
  2954                              <1> 	;        sret   / tap0
  2955                              <1> 	;        sret   / tap1
  2956                              <1> 	;        sret   / tap2
  2957                              <1> 	;        sret   / tap3
  2958                              <1> 	;        sret   / tap4
  2959                              <1> 	;        sret   / tap5
  2960                              <1> 	;        sret   / tap6
  2961                              <1> 	;        sret   / tap7
  2962                              <1> 	;        ccvt   / tty0
  2963                              <1> 	;        ccvt   / tty1
  2964                              <1> 	;        ccvt   / tty2
  2965                              <1> 	;        ccvt   / tty3
  2966                              <1> 	;        ccvt   / tty4
  2967                              <1> 	;        ccvt   / tty5
  2968                              <1> 	;        ccvt   / tty6
  2969                              <1> 	;        ccvt   / tty7
  2970                              <1> 	;        error / crd
  2971                              <1> 
  2972                              <1> ;iclose_2: ; 2: / negative i-number
  2973                              <1> 	;neg	ax
  2974                              <1> 		;neg r1 / make it positive
  2975                              <1> 	;cmp	ax, 40
  2976                              <1> 		;cmp r1,$40. / is it a special file?
  2977                              <1>         ;ja	short @b
  2978                              <1> 		;bgt    3b / no. return
  2979                              <1> 	;push	ax
  2980                              <1> 		;mov r1,-(sp)
  2981                              <1> 	;movzx	ebx, al
  2982                              <1> 	;shl	bx, 1
  2983                              <1> 		;asl r1 / yes. compute jump address and transfer
  2984                              <1> 	;add	ebx, iclose_3 - 2
  2985                              <1> 	;jmp	dword [ebx]
  2986                              <1> 		;jmp *1f-2(r1) / figure out 
  2987                              <1> ;iclose_3:
  2988                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2989                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2990                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2991                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2992                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2993                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2994                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2995                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2996                              <1> 	 ;dd	sret ; lpr, AX = 9	
  2997                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2998                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2999                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  3000                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  3001                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  3002                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  3003                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  3004                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  3005                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  3006                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  3007                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  3008                              <1> 	
  3009                              <1> 	;1:
  3010                              <1> 	;      	ctty   / tty
  3011                              <1> 	;       leadr  / ppt
  3012                              <1> 	;       sret   / mem
  3013                              <1> 	;       sret   / rf0
  3014                              <1> 	;       sret   / rk0
  3015                              <1> 	;       sret   / tap0
  3016                              <1> 	;       sret   / tap1
  3017                              <1> 	;       sret   / tap2
  3018                              <1> 	;       sret   / tap3
  3019                              <1> 	;       sret   / tap4
  3020                              <1> 	;       sret   / tap5
  3021                              <1> 	;       sret   / tap6
  3022                              <1> 	;       sret   / tap7
  3023                              <1> 	;       ccvt   / tty0
  3024                              <1> 	;       ccvt   / tty1
  3025                              <1> 	;       ccvt   / tty2
  3026                              <1> 	;       ccvt   / tty3
  3027                              <1> 	;       ccvt   / tty4
  3028                              <1> 	;       ccvt   / tty5
  3029                              <1> 	;       ccvt   / tty6
  3030                              <1> 	;       ccvt   / tty7
  3031                              <1> 	;/      ejec   / lpr
  3032                              <1> 
  3033                              <1> ctty: ; / close console tty
  3034                              <1> 	; 26/02/2022
  3035                              <1> 	; 09/02/2022
  3036                              <1> 	; 06/02/2022
  3037                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3038                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  3039                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  3040                              <1> 	;
  3041                              <1> 	; Retro UNIX 8086 v1 modification !
  3042                              <1> 	; (DL = 2 -> it is open for reading)
  3043                              <1> 	; (DL = 1 -> it is open for writing)
  3044                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3045                              <1> 	;
  3046                              <1> 	; 06/12/2013
  3047 00005B75 0FB61D[9B6F0000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3048 00005B7C 8A83[A76C0000]      <1>         mov     al, [ebx+p.ttyc-1]
  3049                              <1> 	; 13/01/2014
  3050                              <1> 	;jmp	short cttyp
  3051                              <1> 	; 06/02/2022
  3052 00005B82 EB04                <1> 	jmp	short ctty_0
  3053                              <1> ccvt:
  3054 00005B84 2C0A                <1> 	sub 	al, 10
  3055                              <1> cttyp:	; (call from sysstty)
  3056                              <1> 	; 08/01/2022
  3057 00005B86 31DB                <1> 	xor	ebx, ebx
  3058                              <1> ctty_0: ; (ebx < 256)  ; 06/02/2022
  3059                              <1> 	; 08/01/2022
  3060                              <1> 	; 18/05/2015 (32 bit modifications)
  3061                              <1> 	; 16/08/2013 - 26/01/2014
  3062                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3063                              <1> 	; 08/01/2022
  3064 00005B88 88C3                <1> 	mov	bl, al
  3065 00005B8A D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3066                              <1> 	; 26/01/2014
  3067 00005B8C 81C3[D46B0000]      <1> 	add 	ebx, ttyl
  3068 00005B92 88C6                <1> 	mov 	dh, al ; tty number
  3069 00005B94 668B03              <1> 	mov 	ax, [ebx]
  3070                              <1> 		   ; AL = lock value (0 or process number)
  3071                              <1> 		   ; AH = open count 
  3072 00005B97 20E4                <1> 	and 	ah, ah
  3073 00005B99 7514                <1> 	jnz	short ctty_ret
  3074                              <1>   	; 09/02/2022
  3075 00005B9B 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3076 00005B9E 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3077                              <1> 	; iclose (dl=1 or dl=2)
  3078 00005BA0 C705[A16F0000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3078 00005BA8 0000                <1>
  3079                              <1> 			; device not open ! error
  3080                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3081 00005BAA E918DFFFFF          <1> 	jmp	error
  3082                              <1> 	; 26/01/2014
  3083                              <1> ctty_ret:
  3084 00005BAF FECC                <1> 	dec 	ah ; decrease open count
  3085 00005BB1 7502                <1> 	jnz	short ctty_1
  3086 00005BB3 30C0                <1> 	xor	al, al ; unlock/free tty
  3087                              <1> ctty_1:
  3088 00005BB5 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3089                              <1> 	;
  3090 00005BB8 BB[7C6F0000]        <1> 	mov	ebx, u.ttyp
  3091                              <1> 	;test	dl, 1 ; open for write sign
  3092                              <1> 	;jz	short ctty_2
  3093                              <1> 	; 26/02/2022
  3094 00005BBD F6C202              <1> 	test	dl, 2 ; open for read sign
  3095 00005BC0 7501                <1> 	jnz	short ctty_2
  3096 00005BC2 43                  <1> 	inc	ebx
  3097                              <1> ctty_2:
  3098 00005BC3 FEC6                <1> 	inc	dh ; tty number + 1
  3099 00005BC5 3A33                <1> 	cmp	dh, [ebx]
  3100                              <1> 	;jne	short cret
  3101 00005BC7 7503                <1> 	jne	short ctty_3 ; 09/02/2022
  3102                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3103 00005BC9 C60300              <1> 	mov	byte [ebx], 0
  3104                              <1> ctty_3:
  3105                              <1> 	; 09/02/2022
  3106 00005BCC 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3107 00005BCE 7401                <1> 	jz	short ctty_4
  3108                              <1> cret:
  3109                              <1> 	;pop	ax
  3110                              <1> 	; 08/01/2022
  3111 00005BD0 58                  <1> 	pop	eax
  3112                              <1> ctty_stc_retn:	; 09/02/2022
  3113                              <1> ctty_4:
  3114 00005BD1 C3                  <1> 	retn
  3115                              <1> 
  3116                              <1> ;ctty_err: ; 13/01/2014
  3117                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3118                              <1> ;	jnz	error
  3119                              <1> ;	stc
  3120                              <1> ;	retn
  3121                              <1> 
  3122                              <1> 	; Original UNIX v1 'ctty' routine:
  3123                              <1> 	;	
  3124                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3125                              <1> 	;		;/ point r5 to the console tty buffer
  3126                              <1>         ;decb   (r5) / dec number of processes using console tty
  3127                              <1>         ;br     sret / return via sret
  3128                              <1> 
  3129                              <1> ;ccvt:	; < close tty >
  3130                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3131                              <1> 	;
  3132                              <1> 	; Retro UNIX 8086 v1 modification !
  3133                              <1> 	; 
  3134                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3135                              <1> 	;		(exactly different than this one)
  3136                              <1> 	;	was in 'u9.s' file.
  3137                              <1> 	;
  3138                              <1> 	; DL = 2 -> it is open for reading
  3139                              <1> 	; DL = 1 -> it is open for writing
  3140                              <1> 	;
  3141                              <1> 	; 17/09/2013
  3142                              <1> 	;sub 	al, 10
  3143                              <1> 	;cmp	al, 7
  3144                              <1> 	;jna	short cttyp
  3145                              <1> 	; 13/01/2014
  3146                              <1> 	;jmp	short cttyp
  3147                              <1> 
  3148                              <1> ;cppt: / close paper tape
  3149                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3150                              <1> ;1:
  3151                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3152                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3153                              <1> ;                          / and assign to free list
  3154                              <1> ;               br sret
  3155                              <1> ;        br     1b
  3156                              <1> 
  3157                              <1> ;ejec:	
  3158                              <1> ;	jmp	error
  3159                              <1> ;/ejec:
  3160                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3161                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3162                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3163                              <1> ;/       br     sret / return to caller via 'sret'
  2107                                  %include 'u8.s'        ; 11/06/2015
  2108                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS8.INC
  2109                              <1> ; Last Modification: 12/02/2022
  2110                              <1> ; ----------------------------------------------------------------------------
  2111                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2112                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2113                              <1> ;
  2114                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2115                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2116                              <1> ; <Bell Laboratories (17/3/1972)>
  2117                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2118                              <1> ;
  2119                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2120                              <1> ;
  2121                              <1> ; ****************************************************************************
  2122                              <1> 
  2123                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2124                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2125                              <1> ;; Word 1, byte 0 = device id
  2126                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2127                              <1> ;;          bit 9 = write bit
  2128                              <1> ;;	    bit 10 = read bit	  
  2129                              <1> ;;	    bit 12 = waiting to write bit	
  2130                              <1> ;;	    bit 13 = waiting to read bit
  2131                              <1> ;;	    bit 15 = inhibit bit
  2132                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2133                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2134                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2135                              <1> ;;
  2136                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2137                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2138                              <1> ;;
  2139                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2140                              <1> ;; Word 1, Byte 0 = device id
  2141                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2142                              <1> ;;          bit 9 = write bit
  2143                              <1> ;;	    bit 10 = read bit	  
  2144                              <1> ;;	    bit 12 = waiting to write bit	
  2145                              <1> ;;	    bit 13 = waiting to read bit
  2146                              <1> ;;	    bit 15 = inhibit bit
  2147                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2148                              <1> ;;
  2149                              <1> ;; Original UNIX v1 ->
  2150                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2151                              <1> ;; Original UNIX v1 -> 
  2152                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2153                              <1> ;;
  2154                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2155                              <1> ;;
  2156                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2157                              <1> ;;          0 = fd0
  2158                              <1> ;;	    1 = fd1
  2159                              <1> ;;	    2 = hd0
  2160                              <1> ;;	    3 = hd1
  2161                              <1> ;;	    4 = hd2
  2162                              <1> ;;	    5 = hd3
  2163                              <1> 
  2164                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2165                              <1> 
  2166                              <1> 	; 08/02/2022
  2167                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2168                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2169                              <1> 	; 26/04/2013
  2170                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2171                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2172                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2173                              <1> 
  2174                              <1> 	; 08/02/2022
  2175                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2176                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2177                              <1> 	; 26/04/2013
  2178                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2179                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2180                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2181                              <1> 
  2182                              <1> bread: 
  2183                              <1> 	; 08/02/2022
  2184                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2185                              <1> 	; 14/07/2015
  2186                              <1> 	; 10/07/2015
  2187                              <1> 	; 09/06/2015
  2188                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2189                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2190                              <1> 	;	
  2191                              <1> 	; / read a block from a block structured device
  2192                              <1> 	;
  2193                              <1> 	; INPUTS ->
  2194                              <1> 	;    [u.fofp] points to the block number
  2195                              <1> 	;    CX = maximum block number allowed on device
  2196                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2197                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2198                              <1> 	;    [u.count]	number of bytes to read in
  2199                              <1> 	; OUTPUTS ->
  2200                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2201                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2202                              <1> 	;
  2203                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2204                              <1> 	;
  2205                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2206                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2207                              <1> 	;	is increased by 1. For example: If user/program request 
  2208                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2209                              <1> 	;  	the next block number just as 512 byte reading is done.
  2210                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2211                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2212                              <1> 	;       enough to keep byte position/offset of the disk), this
  2213                              <1> 	;	defect will not be corrected, user/program must request
  2214                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2215                              <1> 	;       for achieving correct result. In future version(s), 
  2216                              <1> 	;	this defect will be corrected by using different 
  2217                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2218                              <1> 
  2219                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2220                              <1> 			       ; / (only works on tape)
  2221                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2222                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2223                              <1> ;1:
  2224                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2225                              <1> 			    ; / maximum block # allowed on device
  2226                              <1> 		; jnb short @f
  2227                              <1> 		; bhis	1f / yes, 1f (error)
  2228                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2229                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2230                              <1> 		; mov (sp)+,r1 / return block # to r1
  2231                              <1> 		; inc r1 / bump block # to next consecutive block
  2232                              <1> 		; dec (sp) / "2-1-cold" on stack
  2233                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2234                              <1> ;1:
  2235                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2236                              <1> 	;push	ecx ; **
  2237                              <1> 	; 26/04/2013
  2238                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2239 00005BD2 2C03                <1> 	sub	al, 3
  2240                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2241 00005BD4 A2[B46F0000]        <1> 	mov	[u.brwdev], al
  2242                              <1> 	; 09/06/2015
  2243                              <1> 	;movzx	ebx, al
  2244                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2245                              <1> 	; 12/01/2022 (BugFix)
  2246 00005BD9 C0E002              <1> 	shl	al, 2 ; * 4
  2247 00005BDC 8B88[AE660000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2248                              <1> bread_0:
  2249 00005BE2 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2250                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2251                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2252 00005BE3 8B1D[5C6F0000]      <1> 	mov	ebx, [u.fofp]
  2253 00005BE9 8B03                <1> 	mov	eax, [ebx]
  2254 00005BEB C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2255                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2256                              <1> 			       ; / block #
  2257 00005BEE 39C8                <1> 	cmp	eax, ecx
  2258                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2259                              <1>        	                     ; / block number allowed
  2260                              <1> 	;jnb	error 	     ; 18/04/2013
  2261                              <1> 		; bhis error10 / yes, error
  2262                              <1> 	; 08/02/2022
  2263                              <1> 	;jb	short bread_1
  2264                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2265                              <1> 	;jmp	error
  2266 00005BF0 735A                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2267                              <1> bread_1:
  2268                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2269                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2270                              <1> 	; eAX = Block number (zero based)
  2271                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2272                              <1> preread: ;; call preread
  2273 00005BF2 BF[B46F0000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2274 00005BF7 E888020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2275                              <1> 	;; jc 	error
  2276                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2277                              <1>         ; eAX = Block/Sector number (r1)
  2278                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2279                              <1> 	; 14/03/2013
  2280 00005BFC 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2281                              <1>        		; br 1f / branch if block already in a I/O buffer
  2282 00005BFE 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2283                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2284 00005C03 E8DA010000          <1> 	call	poke
  2285                              <1>         	; jsr r0,poke / perform the read
  2286                              <1> 	;;jc	error ;2 0/07/2013
  2287                              <1> ; 1:
  2288                              <1>  		; clr *$ps / ps = 0
  2289                              <1>         	; rts r0
  2290                              <1> 	; 08/02/2022
  2291 00005C08 7305                <1> 	jnc	short bread_2
  2292 00005C0A E937010000          <1> 	jmp	dskrd_err
  2293                              <1> 	;
  2294                              <1> ;; return from preread
  2295                              <1> bread_2:
  2296 00005C0F 66810B0040          <1> 	or	word [ebx], 4000h 
  2297                              <1> 		; bis $40000,(r5) 
  2298                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2299                              <1> bread_3: ; 1:
  2300 00005C14 66F7030024          <1> 	test	word [ebx], 2400h
  2301                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2302 00005C19 7407                <1> 	jz	short bread_4
  2303                              <1> 		; beq 1f / no
  2304                              <1> 		; cmp cdev,$1 / disk or drum?
  2305                              <1> 		; ble 2f / yes
  2306                              <1> 		; tstb uquant / is the time quantum = 0?
  2307                              <1> 		; bne 2f / no, 2f
  2308                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2309                              <1> 		; jsr r0,sleep; 31. 
  2310                              <1> 			; / put process to sleep in channel 31 (tape)
  2311                              <1> 		; mov (sp)+,r5 / restore r5
  2312                              <1> 		; br 1b / go back
  2313                              <1> ; 2: / drum or disk
  2314                              <1>         ;; mov	cx, [s.wait_]+2 ;; 29/07/2013
  2315 00005C1B E856F3FFFF          <1> 	call	idle
  2316                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2317 00005C20 EBF2                <1> 	jmp	short bread_3
  2318                              <1>        		; br 1b
  2319                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2320 00005C22 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2321                              <1> 		; bic $40000,(r5) / clear bit 14
  2322                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2323 00005C27 83C308              <1> 	add	ebx, 8
  2324                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2325                              <1> 	; 09/06/2015
  2326 00005C2A 66833D[B16F0000]00  <1> 	cmp	word [u.pcount], 0
  2327 00005C32 7705                <1> 	ja	short bread_5
  2328 00005C34 E814F9FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2329                              <1> bread_5:
  2330                              <1> 	; eBX = system (I/O) buffer address
  2331 00005C39 E870000000          <1> 	call	dioreg
  2332                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2333                              <1> 	; esi = start address of the transfer (in the buffer)
  2334                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2335                              <1> 	; ecx = transfer count (in bytes)
  2336                              <1> 	;
  2337                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2338                              <1> ;   / of users data
  2339 00005C3E F3A4                <1> 	rep	movsb
  2340                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2341                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2342                              <1>        		; bne 1b
  2343 00005C40 59                  <1> 	pop	ecx ; **
  2344 00005C41 833D[706F0000]00    <1> 	cmp	dword [u.count], 0
  2345                              <1> 		; tst u.count / done
  2346 00005C48 7798                <1> 	ja	short bread_0 ; 09/06/2015
  2347                              <1>        		; beq 1f / yes, return
  2348                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2349                              <1>        		; br bread / read some more
  2350                              <1> ; 1:
  2351 00005C4A 58                  <1> 	pop	eax ; ****
  2352                              <1>        		; mov (sp)+,r0
  2353 00005C4B C3                  <1>         retn		; 09/06/2015
  2354                              <1> 	;jmp	ret_ 
  2355                              <1> 		;jmp ret  / jump to routine that called readi
  2356                              <1> 
  2357                              <1> 	; 08/02/2022
  2358                              <1> brw_oov_err:
  2359 00005C4C C705[A16F0000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2359 00005C54 0000                <1>
  2360 00005C56 E96CDEFFFF          <1> 	jmp	error
  2361                              <1> 
  2362                              <1> 	; 08/02/2022
  2363                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2364                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2365                              <1> 	; 26/04/2013
  2366                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2367                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2368                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2369                              <1> 
  2370                              <1> 
  2371                              <1> 	; 08/02/2022
  2372                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)				
  2373                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2374                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2375                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2376                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2377                              <1> 
  2378                              <1> bwrite:
  2379                              <1> 	; 08/02/2022
  2380                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2381                              <1> 	; 14/07/2015
  2382                              <1> 	; 10/07/2015
  2383                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2384                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2385                              <1> 	;	
  2386                              <1> 	;; / write on block structured device
  2387                              <1> 	;
  2388                              <1> 	; INPUTS ->
  2389                              <1> 	;    [u.fofp] points to the block number
  2390                              <1> 	;    CX = maximum block number allowed on device
  2391                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2392                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2393                              <1> 	;    [u.count]	number of bytes to user desires to write
  2394                              <1> 	; OUTPUTS ->
  2395                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2396                              <1> 	;
  2397                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2398                              <1> 	;
  2399                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2400                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2401                              <1> 	;	is increased by 1. For example: If user/program request 
  2402                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2403                              <1> 	;  	the next block number just as 512 byte writing is done.
  2404                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2405                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2406                              <1> 	;       enough to keep byte position/offset of the disk), this
  2407                              <1> 	;	defect will not be corrected, user/program must request
  2408                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2409                              <1> 	;       for achieving correct result. In future version(s), 
  2410                              <1> 	;	this defect will be corrected by using different 
  2411                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2412                              <1> 
  2413                              <1>        		; jsr r0,tstdeve / test the device for an error
  2414                              <1> 	;push	ecx ; **
  2415                              <1> 	; 26/04/2013
  2416                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2417 00005C5B 2C03                <1> 	sub	al, 3
  2418                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2419 00005C5D A2[B46F0000]        <1> 	mov	[u.brwdev], al
  2420                              <1> 	; 09/06/2015
  2421                              <1> 	;movzx	ebx, al
  2422                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2423                              <1> 	; 12/01/2022 (BugFix)
  2424 00005C62 C0E002              <1> 	shl	al, 2 ; * 4
  2425 00005C65 8B88[AE660000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2426                              <1> bwrite_0:
  2427 00005C6B 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2428                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2429                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2430 00005C6C 8B1D[5C6F0000]      <1> 	mov	ebx, [u.fofp]
  2431 00005C72 8B03                <1> 	mov	eax, [ebx]       
  2432 00005C74 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2433                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2434 00005C77 39C8                <1> 	cmp	eax, ecx
  2435                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2436                              <1>        	                     ; / block number allowed
  2437                              <1> 	;jnb	error	     ; 18/04/2013
  2438                              <1> 		; bhis error10 / yes, error
  2439                              <1>      	; 08/02/2022
  2440                              <1> 	;jb	short bwrite_1
  2441                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2442                              <1> 	;jmp	error
  2443 00005C79 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2444                              <1> bwrite_1:
  2445                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2446                              <1> 		; inc *u.fofp / no, increment block number
  2447                              <1> 	; 09/06/2015 - 10/07/2015
  2448 00005C7B 66833D[B16F0000]00  <1> 	cmp	word [u.pcount], 0
  2449 00005C83 7705                <1> 	ja	short bwrite_2
  2450 00005C85 E8BFF8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2451                              <1> bwrite_2:
  2452 00005C8A BF[B46F0000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2453 00005C8F E8D3000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2454                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2455                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2456 00005C94 E815000000          <1>         call	dioreg
  2457                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2458                              <1> 	; esi = destination address (in the buffer)
  2459                              <1> 	; edi = [u.pbase], start address of transfer in user's memory space
  2460                              <1> 	; ecx = transfer count (in bytes)
  2461                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2462 00005C99 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2463 00005C9B F3A4                <1> 	rep	movsb
  2464                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2465                              <1>        		; dec r3 / area to the I/O buffer
  2466                              <1>        		; bne 1b
  2467 00005C9D E80D010000          <1> 	call	dskwr
  2468                              <1> 		; jsr r0,dskwr / write it out on the device
  2469 00005CA2 59                  <1> 	pop	ecx ; **
  2470 00005CA3 833D[706F0000]00    <1>         cmp     dword [u.count], 0
  2471                              <1> 		; tst u.count / done
  2472 00005CAA 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2473                              <1> 		; beq 1f / yes, 1f
  2474                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2475                              <1>        		; br bwrite / go back and write next block
  2476                              <1> ; 1:
  2477 00005CAC 58                  <1> 	pop	eax ; ****
  2478                              <1>        		; mov (sp)+,r0
  2479 00005CAD C3                  <1> 	retn		; 09/06/2015
  2480                              <1>         ;jmp	ret_ 
  2481                              <1> 		; jmp ret / return to routine that called writei
  2482                              <1> ;error10:
  2483                              <1> ;       jmp     error  ; / see 'error' routine
  2484                              <1> 
  2485                              <1> dioreg:
  2486                              <1> 	; 04/02/2022
  2487                              <1> 	; 14/07/2015
  2488                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2489                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2490                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2491                              <1> 	;	
  2492                              <1> 	; bookkeeping on block transfers of data
  2493                              <1> 	;
  2494                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2495                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2496                              <1> 	; 10/07/2015
  2497                              <1> 	; * returns byte offset from beginning of current sector buffer
  2498                              <1> 	; (beginning of data) in ESI
  2499                              <1> 	;
  2500 00005CAE 8B0D[706F0000]      <1> 	mov	ecx, [u.count]
  2501                              <1> 		; mov u.count,r3 / move char count to r3
  2502                              <1> 	; 04/02/2022
  2503 00005CB4 31D2                <1> 	xor	edx, edx
  2504 00005CB6 B602                <1> 	mov	dh, 2
  2505                              <1> 	; edx = 512
  2506 00005CB8 39D1                <1> 	cmp	ecx, edx ; 512
  2507                              <1> 	;cmp 	ecx, 512
  2508                              <1> 		; cmp r3,$512. / more than 512. char?
  2509 00005CBA 7602                <1> 	jna	short dioreg_0
  2510                              <1> 		; blos 1f / no, branch
  2511 00005CBC 89D1                <1> 	mov	ecx, edx ; 512
  2512                              <1> 	;mov	ecx, 512
  2513                              <1> 		; mov $512.,r3 / yes, just take 512.
  2514                              <1> dioreg_0:
  2515                              <1> 	; 09/06/2015
  2516 00005CBE 663B0D[B16F0000]    <1> 	cmp	cx, [u.pcount]
  2517 00005CC5 7607                <1> 	jna	short dioreg_1
  2518 00005CC7 668B0D[B16F0000]    <1> 	mov	cx, [u.pcount]
  2519                              <1> dioreg_1:
  2520                              <1> ; 1:
  2521 00005CCE 8B15[6C6F0000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2522                              <1> 	        ; mov u.base,r2 / put users base in r2
  2523 00005CD4 010D[746F0000]      <1> 	add	[u.nread], ecx
  2524                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2525 00005CDA 290D[706F0000]      <1> 	sub	[u.count], ecx
  2526                              <1> 		; sub r3,u.count / update count
  2527 00005CE0 010D[6C6F0000]      <1> 	add	[u.base], ecx
  2528                              <1> 		; add r3,u.base / update base
  2529                              <1> 	; 10/07/2015
  2530                              <1> 	; Retro UNIX 386 v1 - modification !
  2531                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2532                              <1> 	; (It will point to next byte position instead of next block no.)
  2533 00005CE6 8B35[5C6F0000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2534 00005CEC 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2535 00005CEE 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2536 00005CF0 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2537 00005CF5 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2538 00005CF7 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2539                              <1> 	; 09/06/2015 - 10/07/2015
  2540 00005CF9 66290D[B16F0000]    <1> 	sub	[u.pcount], cx
  2541 00005D00 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2542 00005D06 8B3D[AD6F0000]      <1> 	mov	edi, [u.pbase]
  2543 00005D0C 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2544 00005D12 01D7                <1> 	add	edi, edx
  2545 00005D14 893D[AD6F0000]      <1> 	mov	[u.pbase], edi
  2546 00005D1A 010D[AD6F0000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2547 00005D20 C3                  <1> 	retn
  2548                              <1> 		; rts r0 / return
  2549                              <1> 
  2550                              <1> dskrd:
  2551                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2552                              <1> 	; 18/08/2015
  2553                              <1> 	; 02/07/2015
  2554                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2555                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2556                              <1> 	;
  2557                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2558                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2559                              <1> 	; (number specified in r1) in the acquired buffer.)
  2560                              <1> 	; If the device is busy at the time dskrd is called,	
  2561                              <1> 	; dskrd calls idle.
  2562                              <1> 	; 
  2563                              <1> 	; INPUTS ->
  2564                              <1> 	;    r1 - block number
  2565                              <1> 	;    cdev - current device number 
  2566                              <1> 	; OUTPUTS ->
  2567                              <1> 	;    r5 - points to first data word in I/O buffer
  2568                              <1> 	;
  2569                              <1> 	; ((AX = R1)) input/output
  2570                              <1> 	; ((BX = R5)) output 
  2571                              <1> 	;
  2572                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2573                              <1> 	;
  2574 00005D21 E851010000          <1> 	call 	bufaloc
  2575                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2576                              <1> 			       ; / get a free I/O buffer
  2577                              <1> 	;;jc	error ; 20/07/2013
  2578 00005D26 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2579                              <1>        		; br 1f / branch if block already in a I/O buffer
  2580                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2581 00005D28 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2582                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2583                              <1> 		               ; / I/O queue entry for buffer
  2584 00005D2D E8B0000000          <1> 	call	poke
  2585                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2586                              <1> 			    ; /	bit 10=1 says read
  2587                              <1> 	; 09/06/2015
  2588                              <1> 	;jnc	short dskrd_1
  2589                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2590                              <1> 	;jmp	error
  2591                              <1> 	; 08/02/2022
  2592 00005D32 7212                <1> 	jc	short dskrd_3
  2593                              <1> dskrd_1: ; 1:
  2594                              <1>        		;clr *$ps
  2595 00005D34 66F7030024          <1>        	test	word [ebx], 2400h
  2596                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2597                              <1> 				; / jump to idle
  2598 00005D39 7407                <1>        	jz	short dskrd_2
  2599                              <1> 		; beq 1f
  2600                              <1>         ;;mov   ecx, [s.wait_]
  2601 00005D3B E836F2FFFF          <1>        	call	idle
  2602                              <1> 		; jsr r0,idle; s.wait+2
  2603 00005D40 EBF2                <1> 	jmp 	short dskrd_1
  2604                              <1>        		; br 1b
  2605                              <1> dskrd_2: ; 1:
  2606 00005D42 83C308              <1>         add	ebx, 8
  2607                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2608                              <1> 			  ; / just read in
  2609 00005D45 C3                  <1>        	retn
  2610                              <1> 		; rts r0
  2611                              <1> dskrd_err: 
  2612                              <1> 	; 08/02/2022
  2613                              <1> 	; (jump from 'bread' error)	
  2614                              <1> dskrd_3:	
  2615                              <1> 	; 08/02/2022
  2616 00005D46 803D[B46F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2617 00005D4D 7509                <1> 	jne	short dskrd_4 ; no
  2618                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2619 00005D4F C605[B46F0000]00    <1> 	mov	byte [u.brwdev], 0
  2620 00005D56 EB0A                <1> 	jmp	short dskrd_5
  2621                              <1> dskrd_4:
  2622 00005D58 C705[A16F0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2622 00005D60 0000                <1>
  2623                              <1> dskrd_5:
  2624 00005D62 E960DDFFFF          <1> 	jmp	error
  2625                              <1> 
  2626                              <1> bwslot:
  2627                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2628                              <1> 	; 10/07/2015
  2629                              <1> 	;	If the block/sector is not placed in a buffer
  2630                              <1> 	;	before 'wslot', it must be read before
  2631                              <1> 	;	it is written! (Otherwise transfer counts less
  2632                              <1> 	;	than 512 bytes will be able to destroy existing 
  2633                              <1> 	;	data on disk.)
  2634                              <1> 	;
  2635                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2636                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2637                              <1> 	; Retro UNIX 8086 v1 modification !
  2638                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2639                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2640                              <1> 	;	-> eAX = block number
  2641                              <1> 	;
  2642 00005D67 E818010000          <1> 	call	bufaloc_0
  2643 00005D6C 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2644                              <1> 	; 12/01/2022
  2645                              <1> 	; ebx = buffer header address
  2646                              <1> bwslot_0:
  2647                              <1> 	; 10/07/2015
  2648 00005D6E 8B35[5C6F0000]      <1> 	mov	esi, [u.fofp]
  2649 00005D74 8B06                <1> 	mov	eax, [esi]
  2650 00005D76 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2651 00005D7B 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2652                              <1> 		       ; recent disk data must be placed in the buffer
  2653 00005D7D 813D[706F0000]0002- <1> 	cmp	dword [u.count], 512
  2653 00005D85 0000                <1>
  2654 00005D87 730F                <1> 	jnb	short wslot_0	
  2655                              <1> bwslot_1:
  2656 00005D89 E89AFFFFFF          <1> 	call	dskrd_0
  2657                              <1> 	; 12/01/2022
  2658                              <1> 	; ebx = buffer data address = buffer header address + 8
  2659 00005D8E 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2660 00005D91 EB05                <1> 	jmp 	short wslot_0
  2661                              <1> 
  2662                              <1> wslot:
  2663                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2664                              <1> 	; 		(32 bit modifications)
  2665                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2666                              <1> 	;
  2667                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2668                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2669                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2670                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2671                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2672                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2673                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2674                              <1> 	;
  2675                              <1> 	; INPUTS ->
  2676                              <1>  	;    r1 - block number
  2677                              <1> 	;    cdev - current (block/disk) device number
  2678                              <1>  	;
  2679                              <1> 	; OUTPUTS ->
  2680                              <1> 	;    bufp - bits 9 and 15 are set, 
  2681                              <1> 	;           the remainder of the word left unchanged
  2682                              <1> 	;    r5 - points to first data word in I/O buffer
  2683                              <1> 	;
  2684                              <1> 	; ((AX = R1)) input/output
  2685                              <1> 	; ((BX = R5)) output 
  2686                              <1> 	;
  2687                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2688                              <1> 
  2689 00005D93 E8DF000000          <1> 	call	bufaloc
  2690                              <1> 	; 10/07/2015
  2691                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2692                              <1>         	; br 1f / word in buffer in r5
  2693                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2694                              <1>         ; eAX = Block/Sector number (r1)
  2695                              <1> wslot_0: ;1:
  2696 00005D98 66F7030024          <1>      	test	word [ebx], 2400h
  2697                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2698                              <1> 				; / of I/O queue entry
  2699 00005D9D 7407                <1> 	jz	short wslot_1
  2700                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2701                              <1> 		     ; / or not waiting to read)
  2702                              <1> 
  2703                              <1>         ;; mov     ecx, [s.wait_] ; 29/07/2013
  2704 00005D9F E8D2F1FFFF          <1> 	call	idle
  2705                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2706                              <1>        	                     ; / idle
  2707 00005DA4 EBF2                <1> 	jmp	short wslot_0
  2708                              <1> 		; br 1b / till finished
  2709                              <1> wslot_1: ;1:
  2710 00005DA6 66810B0082          <1>         or      word [ebx], 8200h
  2711                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2712                              <1>                             	 ; / (write, inhibit bits)
  2713                              <1>        		; clr     *$ps / clear processor status
  2714 00005DAB 83C308              <1>         add	ebx, 8 ; 11/06/2015
  2715                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2716                              <1> 			  ; / for this block
  2717                              <1> dskwr_1:	; 08/02/2022
  2718 00005DAE C3                  <1>        	retn
  2719                              <1> 		; rts r0
  2720                              <1> dskwr:
  2721                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2722                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2723                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2724                              <1> 	;
  2725                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2726                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2727                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2728                              <1> 	; previously has supplied all the information required in the
  2729                              <1> 	; I/O queue entry.
  2730                              <1> 	;
  2731                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2732                              <1> 	;
  2733                              <1> 	;
  2734 00005DAF 8B1D[0C6F0000]      <1> 	mov	ebx, [bufp]
  2735 00005DB5 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2736                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2737                              <1>                                   ; / bottom of queue
  2738 00005DBA E823000000          <1> 	call	poke
  2739                              <1> 	; 09/06/2015
  2740 00005DBF 73ED                <1> 	jnc	short dskwr_1
  2741                              <1> 	; 08/02/2022
  2742 00005DC1 803D[B46F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2743 00005DC8 7509                <1> 	jne	short dskwr_0 ; no
  2744                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2745 00005DCA C605[B46F0000]00    <1> 	mov	byte [u.brwdev], 0
  2746 00005DD1 EB0A                <1> 	jmp	short dskwr_2
  2747                              <1> dskwr_0:
  2748 00005DD3 C705[A16F0000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2748 00005DDB 0000                <1>
  2749                              <1> dskwr_2:
  2750 00005DDD E9E5DCFFFF          <1> 	jmp	error
  2751                              <1> ;dskwr_1:
  2752                              <1> ;	retn
  2753                              <1> 
  2754                              <1> ;ppoke:
  2755                              <1>        		; mov $340,*$ps
  2756                              <1>        		; jsr r0,poke
  2757                              <1>        		; clr *$ps
  2758                              <1> 		; rts r0
  2759                              <1> poke:
  2760                              <1> 	; 24/12/2021 (32 bit reg push-pop)
  2761                              <1> 	; 24/10/2015
  2762                              <1> 	; 20/08/2015
  2763                              <1> 	; 18/08/2015
  2764                              <1> 	; 02/07/2015
  2765                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2766                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2767                              <1> 	;
  2768                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2769                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2770                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2771                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2772                              <1> 	;
  2773                              <1> 	; Basic I/O functions for all block structured devices
  2774                              <1> 	;
  2775                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2776                              <1> 	;
  2777                              <1> 	; 20/07/2013 modifications
  2778                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2779                              <1> 	; INPUTS -> 
  2780                              <1> 	;        (EBX = buffer header address)
  2781                              <1> 	; OUTPUTS ->
  2782                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2783                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2784                              <1> 	;		(drive not ready or r/w error!)
  2785                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2786                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2787                              <1> 	;        (also it indicates invalid buffer data)
  2788                              <1> 	;
  2789 00005DE2 53                  <1> 	push	ebx
  2790                              <1>        		; mov r1,-(sp)
  2791                              <1>        		; mov r2,-(sp)
  2792                              <1>        		; mov r3,-(sp)
  2793 00005DE3 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2794                              <1> 	;
  2795                              <1> 	; 09/06/2015
  2796                              <1> 	; (permit read/write after a disk  R/W error)
  2797 00005DE4 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2798 00005DE6 B001                <1> 	mov	al, 1
  2799 00005DE8 D2E0                <1> 	shl	al, cl
  2800 00005DEA 8405[326F0000]      <1> 	test 	al, [active] ; busy ? (error)
  2801 00005DF0 7408                <1> 	jz	short poke_0
  2802 00005DF2 F6D0                <1> 	not	al
  2803 00005DF4 2005[326F0000]      <1> 	and	[active], al ; reset busy bit for this device only
  2804                              <1> poke_0:
  2805 00005DFA BE[2C6F0000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2806                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2807                              <1> 					 ; / I/O queue pointer
  2808                              <1> poke_1: ; 1:
  2809 00005DFF 83EE04              <1>         sub	esi, 4
  2810 00005E02 8B1E                <1> 	mov	ebx, [esi]
  2811                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2812 00005E04 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2813 00005E07 F6C406              <1>        	test	ah, 06h
  2814                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2815                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2816                              <1> 			       ; / queue entry
  2817 00005E0A 745C                <1>         jz      short poke_5
  2818                              <1> 		; beq 2f / branch to 2f if both are clear
  2819                              <1> 	; 31/07/2013
  2820                              <1> 	;test	ah, 0B0h ; (*)
  2821                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2822                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2823                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2824                              <1> 		; bne 2f / branch if any are set
  2825                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2826                              <1>     		; movb (r1),r3 / get device id
  2827 00005E0C 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2828                              <1> 	;mov	edi, ecx ; 26/04/2013
  2829 00005E0F 31C0                <1> 	xor 	eax, eax ; 0
  2830                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2831                              <1> 		; tstb deverr(r3) / test for errors on this device
  2832                              <1>        	;jna	short poke_2 
  2833                              <1> 		; beq 3f / branch if no errors
  2834                              <1> 	; 02/07/2015
  2835                              <1> 	;dec	eax
  2836                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2837                              <1>        		; mov $-1,2(r1) / destroy associativity
  2838                              <1> 	;shr	eax, 24
  2839                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2840                              <1> 		; clrb 1(r1) / do not do I/O
  2841                              <1> 	;jmp	short poke_5
  2842                              <1>         ;       ; br 2f
  2843                              <1>                 ; rts r0
  2844                              <1> poke_2: ; 3:
  2845                              <1> 	; 02/07/2015
  2846 00005E11 FEC1                <1> 	inc	cl ; 0FFh -> 0
  2847 00005E13 7453                <1> 	jz	short poke_5
  2848 00005E15 FEC0                <1> 	inc	al ; mov ax, 1
  2849 00005E17 FEC9                <1> 	dec	cl
  2850 00005E19 7402                <1> 	jz	short poke_3
  2851                              <1> 	; 26/04/2013 Modification
  2852                              <1> 	;inc	al ; mov ax, 1
  2853                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2854                              <1> 	;jz	short poke_3 ; cl = 0
  2855 00005E1B D2E0                <1> 	shl	al, cl ; shl ax, cl
  2856                              <1> poke_3:
  2857                              <1> 	;test	[active], ax
  2858 00005E1D 8405[326F0000]      <1> 	test	[active], al
  2859                              <1> 		; bit $2,active / test disk busy bit
  2860 00005E23 7543                <1> 	jnz     short poke_5
  2861                              <1> 		; bne 2f / branch if bit is set
  2862                              <1> 	;or	[active], ax
  2863 00005E25 0805[326F0000]      <1> 	or	[active], al
  2864                              <1> 		; bis $2,active / set disk busy bit
  2865                              <1> 	;push	ax
  2866                              <1> 	; 24/12/2021
  2867 00005E2B 50                  <1> 	push	eax
  2868 00005E2C E8C9000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2869                              <1> 	;mov    [edi+drv.error], ah
  2870                              <1> 	; 24/12/2021
  2871 00005E31 58                  <1> 	pop	eax
  2872                              <1> 	;pop	ax
  2873 00005E32 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2874                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2875                              <1> 	;jna	short poke_4
  2876                              <1> 		; tstb deverr(r3) / test for errors on this device
  2877                              <1>        		; beq 3f / branch if no errors
  2878                              <1> 	; 02/07/2015 (32 bit modification)
  2879                              <1> 	; 20/07/2013
  2880 00005E34 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2881                              <1>        		; mov $-1,2(r1) / destroy associativity
  2882 00005E3B 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2883                              <1> 		; clrb 1(r1) / do not do I/O
  2884 00005E40 EB26                <1> 	jmp     short poke_5
  2885                              <1> poke_4:	; 20/07/2013
  2886                              <1> 	; 17/07/2013
  2887 00005E42 F6D0                <1> 	not 	al 
  2888 00005E44 2005[326F0000]      <1> 	and	[active], al ; reset, not busy
  2889                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2890                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2891 00005E4A 668B03              <1> 	mov	ax, [ebx]
  2892                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2893 00005E4D 66250006            <1>         and	ax, 600h
  2894                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2895 00005E51 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2896                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2897 00005E56 C0E403              <1> 	shl	ah, 3
  2898                              <1>        		; rol r3
  2899                              <1>                 ; rol r3
  2900                              <1>                 ; rol r3	
  2901 00005E59 660903              <1> 	or	[ebx], ax
  2902                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2903                              <1> 			   ; bits 12 and 13
  2904 00005E5C E815F1FFFF          <1> 	call	idle ; 18/01/2014
  2905                              <1> 	;; sti
  2906                              <1> 	;hlt 	; wait for a hardware interrupt
  2907                              <1> 	;; cli
  2908                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2909                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2910                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2911                              <1> 	; method, this procedure will wait for a time according to
  2912                              <1> 	; multi tasking and time sharing concept.
  2913                              <1> 	;
  2914                              <1> 	; 24/10/2015
  2915                              <1> 	;not	ax 
  2916 00005E61 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2917 00005E65 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2918                              <1> poke_5: ;2:
  2919 00005E68 81FE[0C6F0000]      <1>         cmp     esi, bufp
  2920                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  2921                              <1>                             ; / has been scanned
  2922 00005E6E 778F                <1> 	ja      short poke_1
  2923                              <1>                ; bhi 1b
  2924                              <1> 	; 24/03/2013
  2925                              <1>        		; mov (sp)+,r3
  2926                              <1>        		; mov (sp)+,r2
  2927                              <1>        		; mov (sp)+,r1
  2928 00005E70 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2929 00005E71 5B                  <1> 	pop 	ebx
  2930                              <1> 	; 02/07/2015 (32 bit modification)
  2931                              <1> 	; 20/07/2013
  2932                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2933 00005E72 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2934                              <1> 	;	
  2935                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2936                              <1> 	; or written successfully; even if an error occurs while
  2937                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2938                              <1> 	;
  2939                              <1> 	; 09/06/2015
  2940 00005E75 F5                  <1> 	cmc
  2941 00005E76 C3                  <1> 	retn
  2942                              <1>                 ; rts r0
  2943                              <1> 
  2944                              <1> bufaloc:
  2945                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2946                              <1> 	; 20/08/2015
  2947                              <1> 	; 19/08/2015
  2948                              <1> 	; 02/07/2015
  2949                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2950                              <1> 	;	     (32 bit modifications)	
  2951                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2952                              <1> 	;
  2953                              <1> 	; bufaloc - Block device I/O buffer allocation
  2954                              <1> 	; 
  2955                              <1> 	; INPUTS ->
  2956                              <1> 	;    r1 - block number
  2957                              <1> 	;    cdev - current (block/disk) device number
  2958                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2959                              <1> 	; OUTPUTS ->
  2960                              <1> 	;    r5 - pointer to buffer allocated
  2961                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2962                              <1> 	;
  2963                              <1> 	; ((AX = R1)) input/output
  2964                              <1> 	; ((BX = R5)) output
  2965                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2966                              <1> 	;    zf=1 -> block already in a I/O buffer
  2967                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2968                              <1> 	;    ((DL = Device ID))
  2969                              <1> 	;    (((DH = 0 or 1)))
  2970                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2971                              <1> 	;    ((CX and DH will not be used after return)))
  2972                              <1> 
  2973                              <1> 	;;push 	esi ; ***
  2974                              <1> 		; mov r2,-(sp) / save r2 on stack
  2975                              <1>        		; mov $340,*$ps / set processor priority to 7
  2976                              <1> 	; 20/07/2013
  2977                              <1> 	; 26/04/2013
  2978                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  2979                              <1> 	;mov	edi, rdev ; offset mdev = offset rdev + 1
  2980                              <1> 	;add	edi, ebx
  2981                              <1> 	; 09/01/2022
  2982 00005E77 0FB63D[2F6F0000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  2983 00005E7E 81C7[306F0000]      <1> 	add	edi, rdev
  2984                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2985                              <1> 			;; eDI points to device id.
  2986 00005E84 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2987                              <1> 	; 11/06/2015
  2988 00005E87 80BB[CA660000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2989 00005E8E 720F                <1> 	jb	short bufaloc_9
  2990 00005E90 C705[A16F0000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2990 00005E98 0000                <1>
  2991 00005E9A E928DCFFFF          <1> 	jmp	error
  2992                              <1> bufaloc_9:
  2993 00005E9F 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2994                              <1> bufaloc_10: ; 02/07/2015
  2995 00005EA1 31ED                <1> 	xor 	ebp, ebp ; 0
  2996 00005EA3 55                  <1> 	push	ebp ; 0
  2997 00005EA4 89E5                <1>         mov     ebp, esp	
  2998                              <1> 	;
  2999                              <1> bufaloc_1: ;1:
  3000                              <1> 		; clr -(sp) / vacant buffer
  3001 00005EA6 BE[0C6F0000]        <1>         mov 	esi, bufp
  3002                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  3003                              <1> 			     ; / entrys in buffer area
  3004                              <1> bufaloc_2: ;2:
  3005 00005EAB 8B1E                <1> 	mov	ebx, [esi]
  3006                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  3007                              <1> 			    ; queue entry into r5
  3008 00005EAD 66F70300F6          <1> 	test	word [ebx], 0F600h
  3009                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  3010 00005EB2 7503                <1>         jnz	short bufaloc_3
  3011                              <1> 		; bne 3f / branch when 
  3012                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  3013                              <1>                        ; / (i.e., buffer busy)
  3014 00005EB4 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  3015                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  3016                              <1> 			; / found points to word 2 of I/O queue entry)
  3017                              <1> bufaloc_3: ;3:
  3018                              <1> 	;mov	dl, [edi] ; 26/04/2013
  3019                              <1> 	;
  3020 00005EB7 3813                <1> 	cmp	[ebx], dl	
  3021                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  3022                              <1> 			       ; / as current device
  3023 00005EB9 7508                <1> 	jne	short bufaloc_4
  3024                              <1>        		; bne 3f
  3025 00005EBB 394304              <1> 	cmp	[ebx+4], eax
  3026                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  3027                              <1> 			     ; / same as current block number
  3028 00005EBE 7503                <1>        	jne	short bufaloc_4
  3029                              <1> 		; bne 3f
  3030                              <1> 	;add	esp, 4
  3031 00005EC0 59                  <1> 	pop	ecx
  3032                              <1>        		; tst (sp)+ / bump stack pointer
  3033 00005EC1 EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  3034                              <1> 				; jump to bufaloc_6 in original Unix v1
  3035                              <1>        		; br 1f / use this buffer
  3036                              <1> bufaloc_4: ;3:
  3037 00005EC3 83C604              <1> 	add	esi, 4 ; 20/08/2015
  3038                              <1> 	;
  3039 00005EC6 81FE[246F0000]      <1> 	cmp	esi, bufp + (nbuf*4)
  3040                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  3041 00005ECC 72DD                <1> 	jb	short bufaloc_2
  3042                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  3043                              <1>                        ; / buffers not checked)
  3044 00005ECE 5E                  <1>         pop	esi
  3045                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  3046                              <1> 			     ; / to last free block
  3047 00005ECF 09F6                <1>        	or	esi, esi 
  3048 00005ED1 7507                <1> 	jnz	short bufaloc_5
  3049                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  3050                              <1> 	        ; / if a free buffer is found branch to 2f
  3051                              <1>         ;; mov  ecx, [s.wait_]
  3052 00005ED3 E89EF0FFFF          <1> 	call	idle
  3053                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  3054 00005ED8 EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  3055                              <1>        		; br 1b
  3056                              <1> bufaloc_5: ;2:
  3057                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3058 00005EDA FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  3059                              <1> bufaloc_6: ;1:
  3060 00005EDC 8B1E                <1>         mov    	ebx, [esi] 
  3061                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3062                              <1> 			     ; / entry in r5
  3063                              <1> 	;; 26/04/2013
  3064                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3065 00005EDE 8813                <1> 	mov 	[ebx], dl
  3066                              <1> 		; movb cdev,(r5) / put current device number 
  3067                              <1> 				 ; / in I/O queue entry
  3068 00005EE0 894304              <1> 	mov 	[ebx+4], eax
  3069                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3070                              <1> 			     ; / of I/O queue entry
  3071                              <1> bufaloc_7: ;1:
  3072 00005EE3 81FE[0C6F0000]      <1>         cmp	esi, bufp
  3073                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3074                              <1> 			     ; / and put latest assigned
  3075 00005EE9 760A                <1> 	jna	short bufaloc_8	
  3076                              <1>        		; blos 1f / buffer on the top 
  3077                              <1> 			; / (this makes if the lowest priority)
  3078 00005EEB 83EE04              <1> 	sub	esi, 4
  3079 00005EEE 8B0E                <1> 	mov	ecx, [esi]
  3080 00005EF0 894E04              <1> 	mov	[esi+4], ecx
  3081                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3082 00005EF3 EBEE                <1> 	jmp 	short bufaloc_7        
  3083                              <1> 		; br 1b
  3084                              <1> bufaloc_8: ;1:
  3085 00005EF5 891E                <1>         mov	[esi], ebx
  3086                              <1> 		; mov r5,(r2)
  3087                              <1> 	;;pop	esi ; ***
  3088                              <1>        		; mov (sp)+,r2 / restore r2
  3089 00005EF7 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3090                              <1> 		; Retro UNIX 8086 v1 modification
  3091                              <1> 		; zf=1 --> block already is in an I/O buffer
  3092                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3093 00005EF9 C3                  <1> 	retn
  3094                              <1> 		; rts r0
  3095                              <1> 
  3096                              <1> diskio:
  3097                              <1> 	; 12/02/2022
  3098                              <1> 	; 10/02/2022
  3099                              <1> 	; 08/02/2022
  3100                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1 2022, Kernel v0.2.1.2)
  3101                              <1> 	; 10/07/2015
  3102                              <1> 	; 02/07/2015
  3103                              <1> 	; 16/06/2015
  3104                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3105                              <1> 	;	     (80386 protected mode modifications)	
  3106                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3107                              <1> 	;
  3108                              <1> 	; Retro UNIX 8086 v1 feature only !
  3109                              <1> 	;
  3110                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3111                              <1> 	; 04/07/2009 - 20/07/2011
  3112                              <1> 	;
  3113                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3114                              <1> 	;
  3115                              <1>         ; INPUTS ->
  3116                              <1> 	; 	   eBX = System I/O Buffer header address
  3117                              <1> 	;
  3118                              <1>         ; OUTPUTS -> cf=0 --> done 
  3119                              <1> 	; 	     cf=1 --> error code in AH
  3120                              <1> 	;	     ; 08/02/2022
  3121                              <1> 	;	     cf=1 & [u.brwdev] = 0FFh -->
  3122                              <1> 	;		error code in [u.error]
  3123                              <1> 	;		
  3124                              <1> 	; (Modified registers: eAX, eCX, eDX)
  3125                              <1> 	
  3126                              <1> ;rw_disk_sector:
  3127                              <1> 	; 12/02/2022
  3128                              <1> 	; 10/02/2022
  3129                              <1> 	; 08/02/2022
  3130                              <1> 	; 10/07/2015
  3131                              <1> 	; 02/07/2015
  3132                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3133                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3134                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3135                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3136                              <1> 	;
  3137                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  3138 00005EFA B602                <1> 	mov	dh, 2
  3139 00005EFC 668B03              <1> 	mov	ax, [ebx] 
  3140                              <1> 	;
  3141 00005EFF 56                  <1> 	push	esi ; ****
  3142 00005F00 53                  <1> 	push	ebx ; ***
  3143                              <1> 	;
  3144 00005F01 0FB6C8              <1> 	movzx	ecx, al
  3145 00005F04 89CE                <1> 	mov	esi, ecx
  3146                              <1> 	;
  3147 00005F06 38F1                <1> 	cmp	cl, dh ; 2
  3148 00005F08 7202                <1> 	jb	short rwdsk0
  3149 00005F0A 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3150                              <1> rwdsk0:
  3151 00005F0C A2[7B660000]        <1> 	mov	[drv], al
  3152 00005F11 81C6[CA660000]      <1> 	add	esi, drv.status
  3153                              <1> 	; 11/06/2015
  3154 00005F17 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3155 00005F1A 7204                <1> 	jb      short rwdsk1
  3156                              <1> 	; 'drive not ready' error
  3157                              <1> 	; 10/02/2022
  3158                              <1> 	; 08/02/2022
  3159                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3160                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3161                              <1> 	;;jmp	error
  3162                              <1> 	;stc	; cf = 1
  3163                              <1> 	;retn
  3164                              <1> 	; 10/02/2022
  3165 00005F1C B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3166 00005F1E EB20                <1> 	jmp	short rwdsk_err1
  3167                              <1> rwdsk1:
  3168 00005F20 F6C402              <1> 	test	ah, 2
  3169                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  3170                              <1> 			 ; write bit
  3171 00005F23 7402                <1> 	jz	short rwdsk2
  3172                              <1> 	;test	ah, 4
  3173                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3174                              <1> 	;		 ; read bit
  3175                              <1> 	;jz	short diskio_ret
  3176 00005F25 FEC6                <1> 	inc	dh ; 03h = write
  3177                              <1> rwdsk2:
  3178 00005F27 88C2                <1> 	mov	dl, al
  3179 00005F29 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3180 00005F2C 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3181 00005F2E C0E102              <1> 	shl	cl, 2
  3182 00005F31 81C1[AE660000]      <1> 	add	ecx, drv.size ; disk size
  3183 00005F37 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3184 00005F39 7214                <1> 	jb      short rwdsk3
  3185                              <1>  	; 'out of volume' error
  3186                              <1> 	; 10/02/2022
  3187                              <1> 	; 08/02/2022
  3188                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3189                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3190                              <1> 	;;jmp	error
  3191                              <1> 	;stc	; cf = 1
  3192                              <1> 	;retn
  3193                              <1> 	; 10/02/2022
  3194 00005F3B B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3195                              <1> rwdsk_err1:
  3196 00005F40 C605[B46F0000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3197 00005F47 890D[A16F0000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3198 00005F4D EB30                <1> 	jmp	short rwdsk_err2
  3199                              <1> rwdsk3:
  3200                              <1> 	; 11/06/2015
  3201 00005F4F 83C304              <1> 	add	ebx, 4 ; buffer address
  3202 00005F52 C605[D26F0000]04    <1> 	mov	byte [retry_count], 4
  3203 00005F59 F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3204 00005F5C 7432                <1>         jz      short rwdsk_chs
  3205                              <1> rwdsk_lba:
  3206                              <1> 	; LBA read/write (with private LBA function) 
  3207                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3208 00005F5E 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3209 00005F61 89C1                <1> 	mov	ecx, eax ; sector number
  3210                              <1> 	; ebx = buffer (data) address
  3211                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3212                              <1> rwdsk_lba_retry:
  3213                              <1> 	;mov	dl, [drv]
  3214                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3215 00005F63 B419                <1> 	mov	ah, 1Ch - 3h ; LBA write function number - 3
  3216 00005F65 00F4                <1> 	add	ah, dh		
  3217 00005F67 B001                <1> 	mov	al, 1
  3218                              <1> 	;int	13h
  3219 00005F69 E82DC6FFFF          <1> 	call	int13h
  3220 00005F6E 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3221 00005F70 730E                <1> 	jnc	short rwdsk_lba_ok
  3222 00005F72 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3223 00005F75 7408                <1>         je      short rwdsk_lba_fails
  3224 00005F77 FE0D[D26F0000]      <1> 	dec	byte [retry_count]
  3225 00005F7D 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3226                              <1> rwdsk_err2:	; 10/02/2022
  3227                              <1> rwdsk_lba_fails:
  3228 00005F7F F9                  <1> 	stc
  3229                              <1> rwdsk_lba_ok:
  3230 00005F80 5B                  <1> 	pop	ebx ; ***
  3231 00005F81 5E                  <1> 	pop	esi ; ****
  3232 00005F82 C3                  <1> 	retn
  3233                              <1> rwdsk_lba_reset:
  3234 00005F83 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3235                              <1> 	;int	13h
  3236 00005F85 E811C6FFFF          <1>         call	int13h
  3237 00005F8A 73D7                <1> 	jnc     short rwdsk_lba_retry
  3238 00005F8C 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3239 00005F8E EBF0                <1> 	jmp	short rwdsk_lba_ok
  3240                              <1> 	;
  3241                              <1> 	; CHS read (convert LBA address to CHS values)	
  3242                              <1> rwdsk_chs:
  3243                              <1> 	; 10/07/2015
  3244 00005F90 81EE[CA660000]      <1> 	sub	esi, drv.status
  3245 00005F96 89F1                <1> 	mov	ecx, esi
  3246 00005F98 81C6[D1660000]      <1> 	add 	esi, drv.error
  3247                              <1> 	; 02/07/2015
  3248                              <1> 	; 16/06/2015
  3249                              <1>  	; 11/06/2015 
  3250 00005F9E 53                  <1> 	push	ebx ; ** ; buffer
  3251 00005F9F D1E1                <1> 	shl	ecx, 1
  3252 00005FA1 51                  <1> 	push	ecx ; * 
  3253                              <1> 	;
  3254 00005FA2 89CB                <1> 	mov	ebx, ecx
  3255 00005FA4 8835[D16F0000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3256 00005FAA 31D2                <1> 	xor	edx, edx ; 0
  3257                              <1> 	; 09/01/2022
  3258                              <1> 	;sub	ecx, ecx 
  3259 00005FAC 81C3[A0660000]      <1>         add     ebx, drv.spt
  3260 00005FB2 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3261                              <1> 		; EDX:EAX = LBA
  3262 00005FB5 F7F1                <1> 	div	ecx
  3263 00005FB7 88D1                <1> 	mov	cl, dl	; sector number - 1
  3264 00005FB9 FEC1                <1> 	inc	cl	; sector number (1 based)
  3265 00005FBB 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3266                              <1> 	;push	cx
  3267                              <1>         ; 09/01/2022
  3268 00005FBC 51                  <1> 	push	ecx
  3269 00005FBD 81C3[92660000]      <1> 	add     ebx, drv.heads
  3270 00005FC3 668B0B              <1> 	mov	cx, [ebx] ; heads
  3271 00005FC6 31D2                <1> 	xor	edx, edx
  3272                              <1> 		; EAX = cylinders * heads + head
  3273 00005FC8 F7F1                <1> 	div	ecx
  3274                              <1> 	;pop	cx     ; sector number
  3275                              <1> 	; 09/01/2022
  3276 00005FCA 59                  <1> 	pop	ecx
  3277 00005FCB 88D6                <1> 	mov	dh, dl ; head number
  3278 00005FCD 8A15[7B660000]      <1> 	mov	dl, [drv]
  3279 00005FD3 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3280 00005FD5 C0E406              <1> 	shl	ah, 6
  3281 00005FD8 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3282                              <1> 		       ; sector (bits 0-7)
  3283 00005FDA 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3284                              <1> 		; CL = sector (bits 0-5)
  3285                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3286                              <1> 		; CH = cylinder (bits 0-7)
  3287                              <1> 		; DH = head
  3288                              <1> 		; DL = drive
  3289                              <1> 	;
  3290 00005FDB C605[D26F0000]04    <1> 	mov	byte [retry_count], 4
  3291                              <1> rwdsk_retry:	
  3292 00005FE2 8A25[D16F0000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3293 00005FE8 B001                <1> 	mov	al, 1 ; sector count	
  3294                              <1> 	;int	13h
  3295 00005FEA E8ACC5FFFF          <1> 	call	int13h
  3296 00005FEF 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3297 00005FF1 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3298 00005FF3 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3299 00005FF6 7408                <1> 	je	short rwdsk_fails
  3300 00005FF8 FE0D[D26F0000]      <1> 	dec	byte [retry_count]
  3301 00005FFE 7504                <1> 	jnz	short rwdsk_reset
  3302                              <1> rwdsk_fails:
  3303 00006000 F9                  <1> 	stc
  3304                              <1> rwdsk_ok:
  3305 00006001 5B                  <1> 	pop	ebx ; ***
  3306 00006002 5E                  <1> 	pop	esi ; ****
  3307 00006003 C3                  <1> 	retn
  3308                              <1> rwdsk_reset:
  3309                              <1> 	; 02/02/2015
  3310 00006004 28E4                <1> 	sub	ah, ah
  3311 00006006 80FA80              <1> 	cmp	dl, 80h
  3312 00006009 7202                <1> 	jb	short rwdsk_fd_reset
  3313 0000600B B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3314                              <1> rwdsk_fd_reset:
  3315                              <1> 	;int	13h
  3316 0000600D E889C5FFFF          <1>         call	int13h
  3317 00006012 73CE                <1> 	jnc	short rwdsk_retry
  3318 00006014 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3319 00006016 EBE9                <1> 	jmp 	short rwdsk_ok
  3320                              <1> 
  3321                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3322                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3323                              <1> ;
  3324                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3325                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3326                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3327                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3328                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3329                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3330                              <1> ; as in original unix v1.
  3331                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3332                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3333                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3334                              <1> ;
  3335                              <1> ; Erdogan tan (10/07/2015) 
  3336                              <1> 
  3337                              <1> ;drum: / interrupt handler
  3338                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3339                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3340                              <1> ;                                      / error
  3341                              <1> ;               br 3f / no, error
  3342                              <1> ;       br      2f / error
  3343                              <1> ;
  3344                              <1> ;disk:
  3345                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3346                              <1> ;       jmp     *$0f
  3347                              <1> ;0:
  3348                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3349                              <1> ;      	        br 3f / no, errors
  3350                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3351                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3352                              <1> ;                        / to 1f
  3353                              <1> ;       br      4f
  3354                              <1> ;1:
  3355                              <1> ;       bit     $20000,rkcs
  3356                              <1> ;       beq     4f / wait for seek complete
  3357                              <1> ;       mov     $0b,0b-2
  3358                              <1> ;       mov     rkap,r1
  3359                              <1> ;2:
  3360                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3361                              <1> ;                          / the disk buffer
  3362                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3363                              <1> ;       inc     r1
  3364                              <1> ;       asr     (r1)
  3365                              <1> ;       asr     (r1)
  3366                              <1> ;       asr     (r1) / reissue request
  3367                              <1> ;       dec     r1
  3368                              <1> ;3:
  3369                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3370                              <1> ;       mov     ac,-(sp)
  3371                              <1> ;       mov     mq,-(sp) / put these on the stack
  3372                              <1> ;       mov     sc,-(sp)
  3373                              <1> ;       jsr     r0,poke
  3374                              <1> ;       mov     (sp)+,sc
  3375                              <1> ;       mov     (sp)+,mq / pop them off stack
  3376                              <1> ;       mov     (sp)+,ac
  3377                              <1> ;4:
  3378                              <1> ;       jmp     retisp / u4-3
  3379                              <1> ;
  3380                              <1> ;trapt:                  / r2 points to the
  3381                              <1> ;       mov     (r0)+,r2 / device control register
  3382                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3383                              <1> ;       tst     (sp)+
  3384                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3385                              <1> ;       bge     4b / device still active so branch
  3386                              <1> ;       bit     (r0),active / was device busy?
  3387                              <1> ;       beq     4b / no, stray interrupt
  3388                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3389                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3390                              <1> ;       bge     2f / if no error jump to 2f
  3391                              <1> ;       tst     (r0)+ / skip on error
  3392                              <1> ; 2:
  3393                              <1> ;       jmp     (r0)
  2108                                  %include 'u9.s'        ; 29/06/2015
  2109                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS9.INC
  2110                              <1> ; Last Modification: 27/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 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2121                              <1> ;
  2122                              <1> ; ****************************************************************************
  2123                              <1> 
  2124                              <1> getch:
  2125                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2126                              <1> 	; 30/06/2015
  2127                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2128 00006018 28C0                <1> 	sub	al, al ; 0
  2129                              <1> getch_q: ; 06/08/2015
  2130 0000601A 8A25[B66B0000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2131 00006020 EB06                <1>         jmp     short getc_n
  2132                              <1> 
  2133                              <1> getc: 
  2134                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2135                              <1> 	; 12/11/2015
  2136                              <1> 	; 15/09/2015
  2137                              <1> 	; 01/07/2015
  2138                              <1> 	; 30/06/2015
  2139                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2140                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2141                              <1> 	;
  2142                              <1> 	; Retro UNIX 8086 v1 modification !
  2143                              <1> 	; 
  2144                              <1> 	; 'getc' gets (next) character 
  2145                              <1> 	;	 from requested TTY (keyboard) buffer 
  2146                              <1> 	; INPUTS ->
  2147                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2148                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2149                              <1> 	;	(Keyboard buffer will point to 
  2150                              <1> 	;			next character at next call)
  2151                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2152                              <1> 	;	(Keyboard buffer will point to 
  2153                              <1> 	;			current character at next call)
  2154                              <1> 	; OUTPUTS ->
  2155                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2156                              <1> 	;     			 ZF=0 -> AX has (current) character
  2157                              <1> 	;      AL = ascii code
  2158                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2159                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2160                              <1> 	; Original UNIX V1 'getc': 
  2161                              <1> 	;		get a character off character list
  2162                              <1> 	;
  2163                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2164                              <1> 	;
  2165                              <1> 	; 30/06/2015 (32 bit modifications)
  2166                              <1> 	; 16/07/2013
  2167                              <1> 	; mov 	[getctty], ah
  2168                              <1> 	;
  2169                              <1> 
  2170 00006022 8A25[A06F0000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2171                              <1> getc_n:
  2172                              <1> 	; 30/06/2015
  2173 00006028 08E4                <1> 	or	ah, ah
  2174 0000602A 740D                <1> 	jz	short getc0 
  2175 0000602C D0E4                <1> 	shl	ah, 1
  2176 0000602E 0FB6DC              <1> 	movzx	ebx, ah
  2177 00006031 81C3[B86B0000]      <1> 	add	ebx, ttychr
  2178 00006037 EB05                <1> 	jmp	short getc1
  2179                              <1> getc0:
  2180 00006039 BB[B86B0000]        <1> 	mov	ebx, ttychr
  2181                              <1> getc1:
  2182 0000603E 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2183                              <1> 				; (by kb_int)	
  2184 00006041 6609C9              <1> 	or	cx, cx
  2185 00006044 7507                <1> 	jnz	short getc2
  2186 00006046 20C0                <1> 	and 	al, al
  2187 00006048 7415                <1> 	jz	short getc_s
  2188                              <1> 	;xor	ax, ax
  2189                              <1> 	; 24/12/2021
  2190 0000604A 31C0                <1> 	xor	eax, eax
  2191 0000604C C3                  <1> 	retn
  2192                              <1> getc2:	
  2193 0000604D 20C0                <1> 	and	al, al
  2194 0000604F 6689C8              <1> 	mov	ax, cx
  2195 00006052 66B90000            <1> 	mov	cx, 0
  2196 00006056 7506                <1> 	jnz	short getc3
  2197                              <1> getc_sn:
  2198 00006058 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2199 0000605B 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2200                              <1> getc3:
  2201 0000605E C3                  <1> 	retn
  2202                              <1> getc_s:
  2203                              <1> 	; 12/11/2015
  2204                              <1> 	; 15/09/2015
  2205                              <1> 	; 01/07/2015
  2206                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2207                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2208                              <1> 	;
  2209                              <1> 	; tty  of the current process is not 
  2210                              <1> 	; current tty (ptty); so, current process only 
  2211                              <1> 	; can use keyboard input when its tty becomes 
  2212                              <1> 	; current tty (ptty).
  2213                              <1> 	; 'sleep' is for preventing an endless lock
  2214                              <1> 	; during this tty input request.
  2215                              <1> 	; (Because, the user is not looking at the video page
  2216                              <1> 	; of the process to undersand there is a keyboard
  2217                              <1> 	; input request.)
  2218                              <1> 	;
  2219                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2220                              <1> 	;
  2221                              <1> 	; 05/10/2013
  2222                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2223                              <1> 	;
  2224                              <1> 	; 10/10/2013
  2225                              <1> gcw0:
  2226 0000605F B10A                <1> 	mov	cl, 10 ; ch = 0
  2227                              <1> gcw1:	
  2228                              <1> 	; 12/11/2015
  2229 00006061 E86EDBFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2230                              <1> 	; 10/10/2013
  2231 00006066 E80BEFFFFF          <1> 	call	idle
  2232 0000606B 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2233                              <1> 				; (by kb_int)
  2234 0000606E 6609C0              <1> 	or	ax, ax
  2235                              <1> ;	jnz	short gcw3
  2236 00006071 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2237                              <1> 	; 30/06/2015
  2238 00006073 FEC9                <1> 	dec	cl
  2239 00006075 75EA                <1> 	jnz	short gcw1
  2240                              <1> 	;
  2241 00006077 8A25[A06F0000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2242                              <1> ;	; 10/12/2013
  2243                              <1> ;	cmp 	ah, [ptty]
  2244                              <1> ;	jne	short gcw2
  2245                              <1> ;	; 14/02/2014
  2246                              <1> ;	cmp	byte [u.uno], 1
  2247                              <1> ;	jna	short gcw0		
  2248                              <1> ;gcw2:
  2249 0000607D E881EFFFFF          <1> 	call	sleep
  2250                              <1> 	;
  2251                              <1> 	; 20/09/2013
  2252 00006082 8A25[A06F0000]      <1> 	mov	ah, [u.ttyn]
  2253 00006088 30C0                <1> 	xor 	al, al
  2254 0000608A EB9C                <1> 	jmp	short getc_n
  2255                              <1> ;gcw3:
  2256                              <1> gcw2: 	; 15/09/2015
  2257                              <1> 	; 10/10/2013
  2258 0000608C 30C9                <1> 	xor	cl, cl
  2259 0000608E EBC8                <1> 	jmp	short getc_sn
  2260                              <1> 
  2261                              <1> putc:	
  2262                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2263                              <1> 	; 13/08/2015
  2264                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2265                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2266                              <1> 	;
  2267                              <1> 	; Retro UNIX 8086 v1 modification !
  2268                              <1> 	; 
  2269                              <1> 	; 'putc' puts a character 
  2270                              <1> 	;	 onto requested (tty) video page or
  2271                              <1> 	;	 serial port
  2272                              <1> 	; INPUTS ->
  2273                              <1> 	;     AL = ascii code of the character
  2274                              <1> 	;     AH = video page (tty) number (0 to 7)
  2275                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2276                              <1> 	; OUTPUTS ->
  2277                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2278                              <1> 	;      			ZF=0 -> AX has (current) character
  2279                              <1> 	;     cf=0 and AH = 0 -> no error
  2280                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2281                              <1> 	; 
  2282                              <1> 	; Original UNIX V1 'putc': 
  2283                              <1> 	;     put a character at the end of character list
  2284                              <1> 	;
  2285                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2286                              <1> 	;
  2287 00006090 80FC07              <1> 	cmp	ah, 7
  2288                              <1>         ;ja	sndc
  2289 00006093 770A                <1>         ja      short sndc ; 24/12/2024
  2290                              <1> 	; 30/06/2015
  2291 00006095 0FB6DC              <1> 	movzx	ebx, ah
  2292                              <1> 	; 13/08/2015
  2293 00006098 B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2294 0000609A E926B3FFFF          <1> 	jmp	write_tty ; 'video.inc'
  2295                              <1> 
  2296                              <1> sndc:   ; <Send character>
  2297                              <1> 	;
  2298                              <1> 	; 12/01/2022
  2299                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2300                              <1> 	; 17/11/2015
  2301                              <1> 	; 16/11/2015
  2302                              <1> 	; 11/11/2015
  2303                              <1> 	; 10/11/2015
  2304                              <1> 	; 09/11/2015
  2305                              <1> 	; 08/11/2015
  2306                              <1> 	; 07/11/2015
  2307                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2308                              <1> 	; 29/10/2015
  2309                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2310                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2311                              <1> 	;
  2312                              <1> 	; Retro UNIX 8086 v1 feature only !
  2313                              <1> 	;
  2314                              <1> 	; ah = [u.ttyn]
  2315                              <1> 	;
  2316                              <1> 	; 30/06/2015
  2317 0000609F 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2318                              <1> 	; 07/11/2015
  2319 000060A2 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2320                              <1> sndc0:
  2321                              <1> 	; 07/11/2015
  2322 000060A5 E8A7EFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2323 000060AA 7405                <1> 	jz	short sndc1
  2324 000060AC E823DBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2325                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2326                              <1> sndc1:
  2327                              <1> 	; 16/11/2015
  2328                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2329                              <1> 	; 24/12/2021
  2330 000060B1 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2331                              <1> sndcx:
  2332 000060B3 8A83[FA6B0000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2333 000060B9 8AA3[F86B0000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2334                              <1> 	;
  2335                              <1> 	; 17/11/2015
  2336                              <1> 	; check 'request for response' status
  2337 000060BF 80BB[F46B0000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2338 000060C6 740A                <1> 	jz	short query
  2339                              <1> response:
  2340 000060C8 FE05[F76B0000]      <1> 	inc 	byte [comqr] ; query or response status
  2341 000060CE B0FF                <1> 	mov	al, 0FFh	 
  2342 000060D0 EB14                <1> 	jmp	short sndc3
  2343                              <1> query:
  2344 000060D2 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2345 000060D4 750E                <1> 	jnz 	short sndc2 ; normal character
  2346                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2347                              <1> 	;je	short sndc2  ; yes, already responded
  2348                              <1> 	; 16/11/2015
  2349                              <1> 	; query: request for response (again)
  2350 000060D6 8883[F86B0000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2351 000060DC FE05[F76B0000]      <1> 	inc 	byte [comqr] ; query or response status
  2352 000060E2 EB02                <1> 	jmp	short sndc3
  2353                              <1> sndc2:
  2354 000060E4 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2355                              <1> sndc3:
  2356 000060E6 8883[FA6B0000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2357 000060EC 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2358                              <1> 	; 30/06/2015
  2359 000060EE E887D4FFFF          <1> 	call	sp_status ; get serial port status
  2360                              <1> 	; AL = Line status, AH = Modem status
  2361                              <1> 	; 07/11/2015
  2362 000060F3 A880                <1> 	test	al, 80h
  2363 000060F5 7504                <1> 	jnz	short sndc4
  2364 000060F7 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2365 000060F9 751A                <1> 	jnz	short sndc5
  2366                              <1> sndc4: 	; Check line status again
  2367                              <1> 	; 16/11/2015
  2368                              <1> 	;push	cx
  2369                              <1> 	; 24/12/2021
  2370 000060FB 51                  <1> 	push	ecx
  2371                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2372                              <1> 	; 12/01/2022
  2373 000060FC 31C9                <1> 	xor	ecx, ecx
  2374 000060FE B106                <1> 	mov	cl, 6
  2375 00006100 E8B7B3FFFF          <1> 	call	WAITF
  2376                              <1> 	;pop	cx
  2377                              <1> 	; 24/12/1021
  2378 00006105 59                  <1> 	pop	ecx
  2379                              <1> 	;
  2380 00006106 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2381 00006108 E86DD4FFFF          <1> 	call	sp_status ; get serial port status
  2382                              <1> 	; 16/11/2015
  2383                              <1> 	; 09/11/2015
  2384                              <1> 	; 08/11/2015
  2385 0000610D A880                <1> 	test	al, 80h	; time out error
  2386 0000610F 7565                <1>         jnz     short sndc7
  2387 00006111 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2388 00006113 7461                <1>         jz	short sndc7
  2389                              <1> sndc5:  
  2390 00006115 8A83[FA6B0000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2391 0000611B 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2392 0000611F 28DE                <1> 	sub	dh, bl
  2393 00006121 EE                  <1> 	out	dx, al	   ; send on serial port
  2394                              <1> 	; 10/11/2015
  2395                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2396                              <1> 	; (to improve text flow to the terminal)
  2397                              <1> 	; ('diskette.inc': 'WAITF')
  2398                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2399                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2400                              <1> 	;push	cx
  2401                              <1> 	; 24/12/2021
  2402 00006122 51                  <1> 	push	ecx
  2403                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2404                              <1> 	; 12/01/2022
  2405 00006123 29C9                <1> 	sub	ecx, ecx
  2406 00006125 B106                <1> 	mov	cl, 6
  2407 00006127 E890B3FFFF          <1> 	call	WAITF
  2408                              <1> 	;pop	cx
  2409                              <1> 	; 24/12/1021
  2410 0000612C 59                  <1> 	pop	ecx
  2411                              <1>     	;
  2412                              <1> 	; 07/11/2015
  2413 0000612D 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2414                              <1> 	;
  2415 0000612F E846D4FFFF          <1> 	call	sp_status ; get serial port status
  2416                              <1> 	; AL = Line status, AH = Modem status
  2417                              <1> 	;
  2418 00006134 E818EFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2419 00006139 7405                <1> 	jz	short sndc6
  2420 0000613B E894DAFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2421                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2422                              <1> sndc6:
  2423 00006140 3C80                <1> 	cmp	al, 80h
  2424 00006142 7332                <1> 	jnb	short sndc7		
  2425                              <1> 	;
  2426 00006144 803D[F76B0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2427 0000614B 7244                <1> 	jb	short sndc8 	; no, normal character
  2428 0000614D 883D[F76B0000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2429                              <1> 	; 17/11/2015
  2430 00006153 E81EEEFFFF          <1> 	call	idle
  2431                              <1> 	;
  2432 00006158 38BB[FA6B0000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2433                              <1>         ;ja	sndc2       ; response (will be followed by
  2434                              <1> 			    ; a normal character)
  2435                              <1> 	; 24/12/2021
  2436 0000615E 7602                <1> 	jna	short sndc_10
  2437 00006160 EB82                <1> 	jmp	sndc2
  2438                              <1> sndc_10:
  2439                              <1> 	; Query request must be responded by the terminal
  2440                              <1> 	; before sending a normal character !
  2441 00006162 53                  <1> 	push	ebx
  2442                              <1> 	;push	cx ; *** cl = character (to be sent)
  2443                              <1> 	; 24/12/2021
  2444 00006163 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2445 00006164 8A25[A06F0000]      <1> 	mov	ah, [u.ttyn]
  2446 0000616A E894EEFFFF          <1> 	call	sleep ; this process will be awakened by
  2447                              <1> 		      ; received data available interrupt
  2448                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2449                              <1> 	; 24/12/2021
  2450 0000616F 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2451 00006170 5B                  <1> 	pop	ebx
  2452 00006171 E93DFFFFFF          <1>         jmp	sndcx
  2453                              <1> sndc7:
  2454                              <1> 	 ; 16/11/2015
  2455 00006176 803D[F76B0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2456 0000617D 7213                <1> 	jb	short sndc9 	; no
  2457                              <1> 	;
  2458 0000617F 88BB[F86B0000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2459 00006185 88BB[FA6B0000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2460                              <1> 	;
  2461 0000618B 883D[F76B0000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2462                              <1> sndc8:
  2463 00006191 F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2464                              <1> sndc9:
  2465                              <1> 	; AL = Line status, AH = Modem status
  2466 00006192 C3                  <1> 	retn
  2467                              <1> 
  2468                              <1> get_cpos:
  2469                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2470                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2471                              <1> 	;
  2472                              <1> 	; INPUT -> bl = video page number
  2473                              <1> 	; RETURN -> dx = cursor position
  2474                              <1> 
  2475 00006193 53                  <1> 	push	ebx
  2476 00006194 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2477 00006197 D0E3                <1> 	shl	bl, 1
  2478 00006199 81C3[A66B0000]      <1> 	add	ebx, cursor_posn
  2479 0000619F 668B13              <1> 	mov	dx, [ebx]
  2480 000061A2 5B                  <1> 	pop	ebx
  2481 000061A3 C3                  <1> 	retn
  2482                              <1> 
  2483                              <1> read_ac_current:
  2484                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2485                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2486                              <1> 	;
  2487                              <1> 	; INPUT -> bl = video page number
  2488                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2489                              <1> 
  2490 000061A4 E886B3FFFF          <1> 	call 	find_position ; 'video.inc'
  2491                              <1> 	; dx = status port
  2492                              <1> 	; esi = cursor location/address
  2493 000061A9 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2494 000061AF 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2495 000061B2 C3                  <1> 	retn
  2496                              <1> 
  2497                              <1> syssleep:
  2498                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2499                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2500                              <1> 	;
  2501                              <1> 	; Retro UNIX 8086 v1 feature only
  2502                              <1> 	; (INPUT -> none)
  2503                              <1> 	;
  2504 000061B3 0FB61D[9B6F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2505 000061BA 8AA3[A76C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2506 000061C0 E83EEEFFFF          <1> 	call	sleep
  2507 000061C5 E91DD9FFFF          <1> 	jmp	sysret
  2508                              <1> 
  2509                              <1> 	; 27/02/2022
  2510                              <1> 	; (u1.s, 'wttyc' & 'wpc_clr')
  2511                              <1> %if 0
  2512                              <1> 
  2513                              <1> vp_clr:
  2514                              <1> 	; Reset/Clear Video Page
  2515                              <1> 	;
  2516                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2517                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2518                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2519                              <1> 	;
  2520                              <1> 	; Retro UNIX 8086 v1 feature only !
  2521                              <1> 	;
  2522                              <1> 	; INPUTS -> 
  2523                              <1> 	;   BL = video page number	 
  2524                              <1> 	;
  2525                              <1> 	; OUTPUT ->
  2526                              <1> 	;   none
  2527                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2528                              <1> 	;
  2529                              <1> 	; 04/12/2013
  2530                              <1> 	sub	al, al
  2531                              <1> 	; al = 0 (clear video page)
  2532                              <1> 	; bl = video page
  2533                              <1> 	mov	ah, 07h
  2534                              <1> 	; ah = 7 (attribute/color)
  2535                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2536                              <1> 	; 24/12/2021
  2537                              <1> 	xor	ecx, ecx
  2538                              <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2539                              <1> 	call	scroll_up
  2540                              <1> 	; bl = video page
  2541                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2542                              <1> 	; 24/12/2021
  2543                              <1> 	xor	edx, edx 
  2544                              <1> 	jmp 	set_cpos
  2545                              <1> 
  2546                              <1> %endif
  2547                              <1> 
  2548                              <1> sysmsg:
  2549                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2550                              <1> 	; 11/11/2015
  2551                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2552                              <1> 	; Print user-application message on user's console tty
  2553                              <1> 	;
  2554                              <1> 	; Input -> EBX = Message address
  2555                              <1> 	;	   ECX = Message length (max. 255)
  2556                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2557                              <1> 	;
  2558 000061CA 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2559                              <1> 	;ja	sysret ; nothing to do with big message size
  2560 000061D0 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2561 000061D2 08C9                <1> 	or	cl, cl
  2562                              <1> 	;jz	sysret
  2563 000061D4 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2564 000061D6 20D2                <1> 	and	dl, dl
  2565 000061D8 7502                <1> 	jnz	short sysmsg0
  2566 000061DA B207                <1> 	mov	dl, 07h ; default color
  2567                              <1> 		; (black background, light gray character)
  2568                              <1> sysmsg0:
  2569 000061DC 891D[6C6F0000]      <1> 	mov	[u.base], ebx
  2570 000061E2 8815[B76B0000]      <1> 	mov	[ccolor], dl ; color attributes
  2571 000061E8 89E5                <1> 	mov	ebp, esp
  2572 000061EA 31DB                <1> 	xor	ebx, ebx ; 0
  2573 000061EC 891D[746F0000]      <1> 	mov	[u.nread], ebx ; 0
  2574                              <1> 	;
  2575 000061F2 381D[B36F0000]      <1> 	cmp	[u.kcall], bl ; 0
  2576 000061F8 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2577                              <1> 	;
  2578 000061FA 890D[706F0000]      <1> 	mov	[u.count], ecx
  2579 00006200 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2580                              <1> 	; 24/12/2021
  2581                              <1> 	; (dword alignment for esp)
  2582 00006201 F6C103              <1> 	test	cl, 3
  2583 00006204 7404                <1> 	jz	short sysmsg_7
  2584 00006206 80C903              <1> 	or	cl, 3
  2585 00006209 41                  <1> 	inc	ecx
  2586                              <1> sysmsg_7:
  2587 0000620A 29CC                <1> 	sub	esp, ecx
  2588 0000620C 89E7                <1> 	mov	edi, esp
  2589 0000620E 89E6                <1> 	mov	esi, esp
  2590 00006210 66891D[B16F0000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2591                              <1> 	; 11/11/2015
  2592 00006217 8A25[7C6F0000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2593                              <1> 	; 0 = none
  2594 0000621D FECC                <1> 	dec	ah
  2595 0000621F 790C                <1> 	jns	short sysmsg1 
  2596 00006221 8A1D[9B6F0000]      <1> 	mov	bl, [u.uno] ; process number	
  2597 00006227 8AA3[A76C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2598                              <1> sysmsg1:
  2599 0000622D 8825[A06F0000]      <1> 	mov	[u.ttyn], ah
  2600                              <1> sysmsg2:
  2601 00006233 E823F5FFFF          <1> 	call	cpass
  2602 00006238 7416                <1> 	jz	short sysmsg5
  2603 0000623A AA                  <1> 	stosb
  2604 0000623B 20C0                <1> 	and	al, al
  2605 0000623D 75F4                <1> 	jnz	short sysmsg2
  2606                              <1> sysmsg3:
  2607 0000623F 80FC07              <1> 	cmp	ah, 7 ; tty number
  2608 00006242 7711                <1> 	ja	short sysmsg6 ; serial port
  2609 00006244 E83E000000          <1> 	call	print_cmsg
  2610                              <1> sysmsg4:
  2611 00006249 89EC                <1> 	mov	esp, ebp	
  2612                              <1> sysmsg8: ; 24/12/2021	
  2613 0000624B E997D8FFFF          <1> 	jmp	sysret
  2614                              <1> sysmsg5:
  2615 00006250 C60700              <1> 	mov	byte [edi], 0
  2616 00006253 EBEA                <1> 	jmp	short sysmsg3
  2617                              <1> sysmsg6:
  2618 00006255 8A06                <1> 	mov	al, [esi]
  2619 00006257 E843FEFFFF          <1> 	call	sndc
  2620 0000625C 72EB                <1> 	jc	short sysmsg4
  2621 0000625E 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2622 00006261 76E6                <1> 	jna	short sysmsg4
  2623 00006263 46                  <1> 	inc 	esi
  2624 00006264 8A25[A06F0000]      <1> 	mov	ah, [u.ttyn]
  2625 0000626A EBE9                <1> 	jmp	short sysmsg6
  2626                              <1> 
  2627                              <1> sysmsgk: ; Temporary (01/07/2015)
  2628                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2629                              <1> 	; (ECX -character count- will not be considered)
  2630 0000626C 8B35[6C6F0000]      <1> 	mov	esi, [u.base]
  2631 00006272 8A25[B66B0000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2632 00006278 8825[A06F0000]      <1> 	mov	[u.ttyn], ah
  2633 0000627E C605[B36F0000]00    <1> 	mov	byte [u.kcall], 0
  2634 00006285 EBB8                <1> 	jmp	short sysmsg3
  2635                              <1> 	
  2636                              <1> print_cmsg: 
  2637                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2638                              <1> 	;
  2639                              <1> 	; print message (on user's console tty) 
  2640                              <1> 	;	with requested color
  2641                              <1> 	;
  2642                              <1> 	; INPUTS:
  2643                              <1> 	;	esi = message address
  2644                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2645                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2646                              <1> 	;
  2647 00006287 AC                  <1> 	lodsb
  2648                              <1> pcmsg1:
  2649 00006288 56                  <1> 	push 	esi
  2650 00006289 0FB61D[A06F0000]    <1>         movzx   ebx, byte [u.ttyn]
  2651 00006290 8A25[B76B0000]      <1> 	mov	ah, [ccolor]
  2652 00006296 E82AB1FFFF          <1> 	call 	write_tty
  2653 0000629B 5E                  <1> 	pop	esi
  2654 0000629C AC                  <1> 	lodsb
  2655 0000629D 20C0                <1> 	and 	al, al  ; 0
  2656 0000629F 75E7                <1> 	jnz 	short pcmsg1
  2657 000062A1 C3                  <1> 	retn
  2658                              <1> 
  2659                              <1> sysgeterr:
  2660                              <1> 	; 16/02/2022 - Retro UNIX 386 v1.1
  2661                              <1> 	; 09/12/2015
  2662                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2663                              <1> 	; Get last error number or page fault count
  2664                              <1> 	; (for debugging)
  2665                              <1> 	;
  2666                              <1> 	; Input -> EBX = return type
  2667                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2668                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2669                              <1> 	;	   FFFFFFFEh = total page fault count
  2670                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2671                              <1> 	;
  2672                              <1> 	; Output -> EAX = last error number or page fault count
  2673                              <1> 	;	   (depending on EBX input)
  2674                              <1> 	; 	
  2675 000062A2 21DB                <1> 	and 	ebx, ebx
  2676 000062A4 750F                <1> 	jnz	short glerr_2
  2677                              <1> glerr_0:
  2678 000062A6 A1[A16F0000]        <1> 	mov	eax, [u.error]
  2679                              <1> glerr_1:
  2680 000062AB A3[4C6F0000]        <1> 	mov	[u.r0], eax
  2681                              <1>  	;retn
  2682                              <1> 	; 16/02/2022 (BugFix)
  2683 000062B0 E932D8FFFF          <1> 	jmp	sysret
  2684                              <1> glerr_2:
  2685 000062B5 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2686 000062B6 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2687 000062B8 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2688 000062B9 75EB                <1> 	jnz	short glerr_0
  2689 000062BB A1[406C0000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2690 000062C0 EBE9                <1>         jmp     short glerr_1
  2691                              <1> glerr_3:
  2692 000062C2 A1[B56F0000]        <1> 	mov 	eax, [u.pfcount]
  2693 000062C7 EBE2                <1> 	jmp	short glerr_1
  2109                                  
  2110                                  ; 07/03/2015
  2111                                  ; Temporary Code
  2112                                  display_disks:
  2113 000062C9 803D[7E660000]00        	cmp 	byte [fd0_type], 0
  2114 000062D0 7605                    	jna 	short ddsks1
  2115 000062D2 E87D000000              	call	pdskm
  2116                                  ddsks1:
  2117 000062D7 803D[7F660000]00        	cmp	byte [fd1_type], 0
  2118 000062DE 760C                    	jna	short ddsks2
  2119 000062E0 C605[6F680000]31        	mov	byte [dskx], '1'
  2120 000062E7 E868000000              	call	pdskm
  2121                                  ddsks2:
  2122 000062EC 803D[80660000]00        	cmp	byte [hd0_type], 0
  2123 000062F3 7654                    	jna	short ddsk6
  2124 000062F5 66C705[6D680000]68-     	mov	word [dsktype], 'hd'
  2124 000062FD 64                 
  2125 000062FE C605[6F680000]30        	mov	byte [dskx], '0'
  2126 00006305 E84A000000              	call	pdskm
  2127                                  ddsks3:
  2128 0000630A 803D[81660000]00        	cmp	byte [hd1_type], 0
  2129 00006311 7636                    	jna	short ddsk6
  2130 00006313 C605[6F680000]31        	mov	byte [dskx], '1'
  2131 0000631A E835000000              	call	pdskm
  2132                                  ddsks4:
  2133 0000631F 803D[82660000]00        	cmp	byte [hd2_type], 0
  2134 00006326 7621                    	jna	short ddsk6
  2135 00006328 C605[6F680000]32        	mov	byte [dskx], '2'
  2136 0000632F E820000000              	call	pdskm
  2137                                  ddsks5:
  2138 00006334 803D[83660000]00        	cmp	byte [hd3_type], 0
  2139 0000633B 760C                    	jna	short ddsk6
  2140 0000633D C605[6F680000]33        	mov	byte [dskx], '3'
  2141 00006344 E80B000000              	call	pdskm
  2142                                  ddsk6:
  2143 00006349 BE[7E680000]            	mov	esi, nextline
  2144 0000634E E806000000              	call	pdskml
  2145                                  pdskm_ok:
  2146 00006353 C3                      	retn
  2147                                  pdskm:
  2148 00006354 BE[6B680000]            	mov	esi, dsk_ready_msg
  2149                                  pdskml:	
  2150 00006359 AC                      	lodsb
  2151 0000635A 08C0                    	or	al, al
  2152 0000635C 74F5                    	jz	short pdskm_ok
  2153 0000635E 56                      	push	esi
  2154 0000635F 31DB                    	xor	ebx, ebx ; 0
  2155                                  			; Video page 0 (bl=0)
  2156 00006361 B407                    	mov	ah, 07h ; Black background, 
  2157                                  			; light gray forecolor
  2158 00006363 E85DB0FFFF              	call	write_tty
  2159 00006368 5E                      	pop	esi
  2160 00006369 EBEE                    	jmp	short pdskml
  2161                                  
  2162 0000636B 90<rep 5h>              align 16
  2163                                  
  2164                                  gdt:	; Global Descriptor Table
  2165                                  	; (30/07/2015, conforming cs)
  2166                                  	; (26/03/2015)
  2167                                  	; (24/03/2015, tss)
  2168                                  	; (19/03/2015)
  2169                                  	; (29/12/2013)
  2170                                  	;
  2171 00006370 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2172                                  	; 18/08/2014
  2173                                  			; 8h kernel code segment, base = 00000000h		
  2174 00006378 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2175                                  			; 10h kernel data segment, base = 00000000h	
  2176 00006380 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2177                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2178 00006388 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2179                                  			; 23h user data segment, base address = 400000h ; CORE
  2180 00006390 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2181                                  			; Task State Segment
  2182 00006398 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2183                                  			       ;  no IO permission in ring 3)
  2184                                  gdt_tss0:
  2185 0000639A 0000                    	dw 0  ; TSS base address, bits 0-15 
  2186                                  gdt_tss1:
  2187 0000639C 00                      	db 0  ; TSS base address, bits 16-23 
  2188                                  	      		; 49h	
  2189 0000639D E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2190 0000639E 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2191                                  gdt_tss2:
  2192 0000639F 00                      	db 0  ; TSS base address, bits 24-31 
  2193                                  
  2194                                  gdt_end:
  2195                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2196                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2197                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2198                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2199                                  
  2200                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2201                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2202                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2203                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2204                                  		; W= Writeable, A= Accessed
  2205                                  	
  2206                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2207                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2208                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2209                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2210                                  
  2211                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2212                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2213                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2214                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2215                                  	
  2216                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2217                                  
  2218                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2219                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2220                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2221                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2222                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2223                                  		; AVL= Available to programmers	
  2224                                  
  2225                                  gdtd:
  2226 000063A0 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2227 000063A2 [70630000]                      dd gdt			; Address of the GDT
  2228                                  
  2229                                  	; 20/08/2014
  2230                                  idtd:
  2231 000063A6 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2232 000063A8 [20690000]                      dd idt			; Address of the IDT
  2233                                  
  2234                                  Align 4
  2235                                  
  2236                                  	; 21/08/2014
  2237                                  ilist:
  2238                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2239                                  	;
  2240                                  	; Exception list
  2241                                  	; 25/08/2014	
  2242 000063AC [24080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2243 000063B0 [2B080000]              	dd	exc1	
  2244 000063B4 [32080000]              	dd 	exc2	
  2245 000063B8 [39080000]              	dd	exc3	
  2246 000063BC [3D080000]              	dd	exc4	
  2247 000063C0 [41080000]              	dd	exc5	
  2248 000063C4 [45080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2249 000063C8 [49080000]              	dd	exc7	
  2250 000063CC [4D080000]              	dd	exc8	
  2251 000063D0 [51080000]              	dd	exc9	
  2252 000063D4 [55080000]              	dd 	exc10	
  2253 000063D8 [59080000]              	dd	exc11
  2254 000063DC [5D080000]              	dd	exc12
  2255 000063E0 [61080000]              	dd	exc13	; 0Dh, General Protection Fault
  2256 000063E4 [65080000]              	dd 	exc14	; 0Eh, Page Fault
  2257 000063E8 [69080000]              	dd	exc15
  2258 000063EC [6D080000]              	dd	exc16
  2259 000063F0 [71080000]              	dd	exc17
  2260 000063F4 [75080000]              	dd 	exc18
  2261 000063F8 [79080000]              	dd	exc19
  2262 000063FC [7D080000]              	dd 	exc20
  2263 00006400 [81080000]              	dd	exc21
  2264 00006404 [85080000]              	dd	exc22
  2265 00006408 [89080000]              	dd	exc23
  2266 0000640C [8D080000]              	dd 	exc24
  2267 00006410 [91080000]              	dd	exc25
  2268 00006414 [95080000]              	dd	exc26
  2269 00006418 [99080000]              	dd	exc27
  2270 0000641C [9D080000]              	dd 	exc28
  2271 00006420 [A1080000]              	dd	exc29
  2272 00006424 [A5080000]              	dd 	exc30
  2273 00006428 [A9080000]              	dd	exc31
  2274                                  	; Interrupt list
  2275 0000642C [5F060000]              	dd	timer_int	; INT 20h
  2276                                  		;dd	irq0	
  2277 00006430 [630B0000]              	dd	keyb_int	; 27/08/2014
  2278                                  		;dd	irq1
  2279 00006434 [7E070000]              	dd	irq2
  2280                                  		; COM2 int
  2281 00006438 [82070000]              	dd	irq3
  2282                                  		; COM1 int
  2283 0000643C [8D070000]              	dd	irq4
  2284 00006440 [98070000]              	dd	irq5
  2285                                  ;DISKETTE_INT: ;06/02/2015
  2286 00006444 [48250000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2287                                  		;dd	irq6
  2288                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2289                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2290 00006448 [140B0000]              	dd	default_irq7	; 25/02/2015
  2291                                  		;dd	irq7
  2292                                  ; Real Time Clock Interrupt
  2293 0000644C [B2090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2294                                  		;dd	irq8	; INT 28h
  2295 00006450 [A8070000]              	dd	irq9
  2296 00006454 [AC070000]              	dd	irq10
  2297 00006458 [B0070000]              	dd	irq11
  2298 0000645C [B4070000]              	dd	irq12
  2299 00006460 [B8070000]              	dd	irq13
  2300                                  ;HDISK_INT1:  ;06/02/2015 	
  2301 00006464 [6F2D0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2302                                  		;dd	irq14
  2303                                  ;HDISK_INT2:  ;06/02/2015
  2304 00006468 [922D0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2305                                  		;dd	irq15	; INT 2Fh
  2306                                  		; 14/08/2015
  2307 0000646C [CF390000]              	dd	sysent		; INT 30h (system calls)
  2308                                  	
  2309                                  	;dd	ignore_int
  2310 00006470 00000000                	dd	0
  2311                                  
  2312                                  ;;;
  2313                                  ;;; 11/03/2015
  2314                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2315                              <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC
  2316                              <1> ; Last Modification: 11/03/2015
  2317                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2318                              <1> ;
  2319                              <1> ; ///////// KEYBOARD DATA ///////////////
  2320                              <1> 
  2321                              <1> ; 05/12/2014
  2322                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2323                              <1> ; 03/06/86  KEYBOARD BIOS
  2324                              <1> 
  2325                              <1> ;---------------------------------------------------------------------------------
  2326                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2327                              <1> ;---------------------------------------------------------------------------------
  2328                              <1> 
  2329                              <1> ;-----	TABLES FOR ALT CASE ------------
  2330                              <1> ;-----	ALT-INPUT-TABLE 
  2331 00006474 524F50514B          <1> K30:	db	82,79,80,81,75
  2332 00006479 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2333                              <1> ;-----	SUPER-SHIFT-TABLE 
  2334 0000647E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2335 00006484 161718191E1F        <1> 	db	22,23,24,25,30,31
  2336 0000648A 202122232425        <1> 	db	32,33,34,35,36,37
  2337 00006490 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2338 00006496 3132                <1> 	db	49,50
  2339                              <1> 
  2340                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2341                              <1> ;-----	KEY_TABLE 
  2342 00006498 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2343 00006499 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2344 0000649E 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2345                              <1> _K6L    equ     $-_K6
  2346                              <1> 
  2347                              <1> ;-----	MASK_TABLE
  2348 000064A0 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2349 000064A1 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2350 000064A6 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2351                              <1> 
  2352                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2353 000064A8 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2354 000064AE 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2355 000064B4 FF7FFF111705        <1> 	db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2356 000064BA 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2357 000064C0 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2358 000064C6 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2359 000064CC 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2360 000064D2 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2361 000064D8 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2362 000064DE 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2363                              <1> 	;				;----- FUNCTIONS ------		
  2364 000064E2 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2365 000064E8 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2366 000064EE 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2367 000064F4 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2368 000064FA 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2369                              <1> 
  2370                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2371 00006500 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2371 00006509 39302D3D0809        <1>
  2372 0000650F 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2372 00006518 705B5D0DFF61736466- <1>
  2372 00006521 67686A6B6C3B27      <1>
  2373 00006528 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2373 00006531 6D2C2E2FFF2AFF20FF  <1>
  2374                              <1> ;-----	LC TABLE SCAN
  2375 0000653A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2376 0000653F 4041424344          <1> 	db	64,65,66,67,68
  2377 00006544 FFFF                <1> 	db	-1,-1			; NL, SL
  2378                              <1> 
  2379                              <1> ;-----	KEYPAD TABLE
  2380 00006546 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2381 0000654C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2382 00006553 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2383                              <1> 
  2384                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2385 00006558 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2385 00006561 28295F2B0800        <1>
  2386 00006567 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2386 00006570 507B7D0DFF41534446- <1>
  2386 00006579 47484A4B4C3A22      <1>
  2387 00006580 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2387 00006589 4D3C3E3FFF2AFF20FF  <1>
  2388                              <1> ;-----	UC TABLE SCAN
  2389 00006592 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2390 00006597 595A5B5C5D          <1> 	db	89,90,91,92,93
  2391 0000659C FFFF                <1> 	db	-1,-1			; NL, SL
  2392                              <1> 
  2393                              <1> ;-----	NUM STATE TABLE
  2394 0000659E 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2394 000065A7 3233302E            <1>
  2395                              <1> 	;
  2396 000065AB FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2397                              <1> 
  2398                              <1> Align	4
  2399                              <1> ;----------------------------------------
  2400                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2401                              <1> ;----------------------------------------
  2402 000065B0 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2403 000065B1 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2404                              <1> 				; (29h default setting for video mode 3)
  2405                              <1> 				; Mode Select register Bits
  2406                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2407                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2408                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2409                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2410                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2411                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2412                              <1> 				;   BIT 6, 7 - Not Used
  2413                              <1> 
  2414                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2415                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2416                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2417                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2418                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2419                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2420                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2421                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2422                              <1> ; Mode & 37h = Video signal OFF
  2423                              <1> 			
  2424                              <1> 
  2425                              <1> ; 26/08/2014
  2426                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2427                              <1> ; Derived from IBM "pc-at" 
  2428                              <1> ; rombios source code (06/10/1985)
  2429                              <1> ; 'dseg.inc'
  2430                              <1> 
  2431                              <1> ;---------------------------------------;
  2432                              <1> ;	SYSTEM DATA AREA		;
  2433                              <1> ;----------------------------------------
  2434 000065B2 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2435                              <1> 
  2436                              <1> ;----------------------------------------
  2437                              <1> ;	KEYBOARD DATA AREAS		;
  2438                              <1> ;----------------------------------------
  2439                              <1> 
  2440 000065B3 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2441 000065B4 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2442 000065B5 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2443 000065B6 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2444 000065B7 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2445 000065B8 [C8650000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2446 000065BC [E8650000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2447 000065C0 [C8650000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2448 000065C4 [C8650000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2449                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2450 000065C8 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2451                              <1> 
  2452                              <1> ; /// End Of KEYBOARD DATA ///
  2315                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2316                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2317                              <1> ; Last Modification: 11/03/2015
  2318                              <1> ;		    (Data section for 'VIDEO.INC')	
  2319                              <1> ;
  2320                              <1> ; ///////// VIDEO DATA ///////////////
  2321                              <1> 
  2322                              <1> video_params:
  2323                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2324                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2325                              <1> 	; VIDEO MODE 3
  2326 000065E8 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2327 000065EF 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2328 000065F4 00000000            <1> 	db	0,0,0,0
  2329                              <1> 
  2330                              <1> ; /// End Of VIDEO DATA ///
  2316                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2317                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2318                              <1> ; Last Modification: 11/03/2015
  2319                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2320                              <1> ;
  2321                              <1> ; *****************************************************************************
  2322                              <1> 
  2323                              <1> ;----------------------------------------
  2324                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2325                              <1> ;	REFERENCED BY POST & BIOS	:
  2326                              <1> ;----------------------------------------
  2327                              <1> 
  2328 000065F8 [5B660000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2329                              <1> 
  2330                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2331                              <1> ;----------------------------------------------------------------
  2332                              <1> ; DISK_BASE							:
  2333                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2334                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2335                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2336                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2337                              <1> ;----------------------------------------------------------------
  2338                              <1> 
  2339                              <1> ;DISK_BASE:	
  2340                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2341                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2342                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2343                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2344                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2345                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2346                              <1> ;	DB	01BH		; GAP LENGTH
  2347                              <1> ;	DB	0FFH		; DTL
  2348                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2349                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2350                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2351                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2352                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2353                              <1> 
  2354                              <1> ;----------------------------------------
  2355                              <1> ;	ROM BIOS DATA AREAS		:
  2356                              <1> ;----------------------------------------
  2357                              <1> 
  2358                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2359                              <1> 
  2360                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2361                              <1> 
  2362                              <1> ;----------------------------------------
  2363                              <1> ;	DISKETTE DATA AREAS		:
  2364                              <1> ;----------------------------------------
  2365                              <1> 
  2366                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2367                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2368                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2369                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2370                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2371                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2372                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2373                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2374                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2375                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2376                              <1> 
  2377                              <1> ;----------------------------------------
  2378                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2379                              <1> ;----------------------------------------
  2380                              <1> 
  2381                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2382                              <1> 
  2383                              <1> ;----------------------------------------
  2384                              <1> ;	TIMER DATA AREA 		:
  2385                              <1> ;----------------------------------------
  2386                              <1> 
  2387                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2388                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2389                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2390                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2391                              <1> 
  2392                              <1> ;----------------------------------------
  2393                              <1> ;	ADDITIONAL MEDIA DATA		:
  2394                              <1> ;----------------------------------------
  2395                              <1> 
  2396                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2397                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2398                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2399                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2400                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2401                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2402                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2403                              <1> 
  2404                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2405                              <1> 
  2406                              <1> ;--------------------------------------------------------
  2407                              <1> ;	DRIVE TYPE TABLE				:
  2408                              <1> ;--------------------------------------------------------
  2409                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2410                              <1> DR_TYPE:
  2411 000065FC 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2412                              <1>                 ;DW      MD_TBL1
  2413 000065FD [1A660000]          <1> 		dd	MD_TBL1
  2414 00006601 82                  <1> 		DB	02+BIT7ON
  2415                              <1> 		;DW      MD_TBL2
  2416 00006602 [27660000]          <1>                 dd      MD_TBL2
  2417 00006606 02                  <1> DR_DEFAULT:	DB	02
  2418                              <1>                 ;DW      MD_TBL3
  2419 00006607 [34660000]          <1> 		dd      MD_TBL3
  2420 0000660B 03                  <1> 		DB	03
  2421                              <1>                 ;DW      MD_TBL4
  2422 0000660C [41660000]          <1> 		dd      MD_TBL4
  2423 00006610 84                  <1> 		DB	04+BIT7ON
  2424                              <1>                 ;DW      MD_TBL5
  2425 00006611 [4E660000]          <1> 		dd      MD_TBL5
  2426 00006615 04                  <1> 		DB	04
  2427                              <1>                 ;DW      MD_TBL6
  2428 00006616 [5B660000]          <1> 		dd      MD_TBL6
  2429                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2430                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2431                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2432                              <1> ;--------------------------------------------------------
  2433                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2434                              <1> ;--------------------------------------------------------
  2435                              <1> ;--------------------------------------------------------
  2436                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2437                              <1> ;--------------------------------------------------------
  2438                              <1> MD_TBL1:        
  2439 0000661A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2440 0000661B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2441 0000661C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2442 0000661D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2443 0000661E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2444 0000661F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2445 00006620 FF                  <1> 	DB	0FFH		; DTL
  2446 00006621 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2447 00006622 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2448 00006623 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2449 00006624 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2450 00006625 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2451 00006626 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2452                              <1> ;--------------------------------------------------------
  2453                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2454                              <1> ;--------------------------------------------------------
  2455                              <1> MD_TBL2:        
  2456 00006627 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2457 00006628 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2458 00006629 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2459 0000662A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2460 0000662B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2461 0000662C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2462 0000662D FF                  <1> 	DB	0FFH		; DTL
  2463 0000662E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2464 0000662F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2465 00006630 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2466 00006631 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2467 00006632 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2468 00006633 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2469                              <1> ;--------------------------------------------------------
  2470                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2471                              <1> ;--------------------------------------------------------
  2472                              <1> MD_TBL3:
  2473 00006634 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2474 00006635 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2475 00006636 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2476 00006637 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2477 00006638 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2478 00006639 1B                  <1> 	DB	01BH		; GAP LENGTH
  2479 0000663A FF                  <1> 	DB	0FFH		; DTL
  2480 0000663B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2481 0000663C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2482 0000663D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2483 0000663E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2484 0000663F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2485 00006640 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2486                              <1> ;--------------------------------------------------------
  2487                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2488                              <1> ;--------------------------------------------------------
  2489                              <1> MD_TBL4:
  2490 00006641 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2491 00006642 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2492 00006643 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2493 00006644 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2494 00006645 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2495 00006646 2A                  <1> 	DB	02AH		; GAP LENGTH
  2496 00006647 FF                  <1> 	DB	0FFH		; DTL
  2497 00006648 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2498 00006649 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2499 0000664A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2500 0000664B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2501 0000664C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2502 0000664D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2503                              <1> ;--------------------------------------------------------
  2504                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2505                              <1> ;--------------------------------------------------------
  2506                              <1> MD_TBL5:
  2507 0000664E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2508 0000664F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2509 00006650 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2510 00006651 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2511 00006652 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2512 00006653 2A                  <1> 	DB	02AH		; GAP LENGTH
  2513 00006654 FF                  <1> 	DB	0FFH		; DTL
  2514 00006655 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2515 00006656 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2516 00006657 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2517 00006658 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2518 00006659 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2519 0000665A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2520                              <1> ;--------------------------------------------------------
  2521                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2522                              <1> ;--------------------------------------------------------
  2523                              <1> MD_TBL6:
  2524 0000665B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2525 0000665C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2526 0000665D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2527 0000665E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2528 0000665F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2529 00006660 1B                  <1> 	DB	01BH		; GAP LENGTH
  2530 00006661 FF                  <1> 	DB	0FFH		; DTL
  2531 00006662 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2532 00006663 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2533 00006664 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2534 00006665 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2535 00006666 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2536 00006667 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2537                              <1> 
  2538                              <1> 
  2539                              <1> ; << diskette.inc >>
  2540                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2541                              <1> ;
  2542                              <1> ;----------------------------------------
  2543                              <1> ;	ROM BIOS DATA AREAS		:
  2544                              <1> ;----------------------------------------
  2545                              <1> 
  2546                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2547                              <1> 
  2548                              <1> ;----------------------------------------
  2549                              <1> ;	FIXED DISK DATA AREAS		:
  2550                              <1> ;----------------------------------------
  2551                              <1> 
  2552                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2553                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2554                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2555                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2556                              <1> 
  2557                              <1> ;----------------------------------------
  2558                              <1> ;	ADDITIONAL MEDIA DATA		:
  2559                              <1> ;----------------------------------------
  2560                              <1> 
  2561                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2562                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2563                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2564                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2565                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2566                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2567                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2568                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2569                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2570                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2571                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2572                              <1> 
  2573                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2574                              <1> ;
  2575                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2576                              <1> 
  2577                              <1> ERR_TBL:
  2578 00006668 E0                  <1> 	db	NO_ERR
  2579 00006669 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2580 0000666D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2581                              <1> 
  2582                              <1> ; 17/12/2014 (mov ax, [cfd])
  2583                              <1> ; 11/12/2014
  2584 00006671 00                  <1> cfd:		db 0			; current floppy drive (for GET_PARM)
  2585                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2586 00006672 01                  <1> pfd:		db 1			; previous floppy drive (for GET_PARM)
  2587                              <1> 					; (initial value of 'pfd 
  2588                              <1> 					; must be different then 'cfd' value
  2589                              <1> 					; to force updating/initializing
  2590                              <1> 					; current drive parameters) 
  2591 00006673 90                  <1> align 2
  2592                              <1> 
  2593 00006674 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2594                              <1> 			      ; (170h)
  2595 00006676 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2596                              <1> 
  2597                              <1> ; 05/01/2015 
  2598 00006678 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2599                              <1> 
  2600                              <1> ; *****************************************************************************
  2317                                  ;;;
  2318                                  
  2319 00006679 90                      Align 2
  2320                                  
  2321                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2322 0000667A 00                      boot_drv:    db 0 ; boot drive number (physical)
  2323                                  ; 24/11/2014
  2324 0000667B 00                      drv:	     db 0 
  2325 0000667C 00                      last_drv:    db 0 ; last hdd
  2326 0000667D 00                      hdc:         db 0  ; number of hard disk drives
  2327                                  		     ; (present/detected)
  2328                                  ;
  2329                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2330                                  ; Physical drive type & flags
  2331 0000667E 00                      fd0_type:    db 0  ; floppy drive type
  2332 0000667F 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2333                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2334                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2335                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2336                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2337 00006680 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2338 00006681 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2339 00006682 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2340 00006683 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2341                                  		     ; bit 0 - Fixed disk access subset supported
  2342                                  		     ; bit 1 - Drive locking and ejecting
  2343                                  		     ; bit 2 - Enhanced disk drive support
  2344                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2345                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2346                                  		     ; will interpret it as 'LBA ready'!)		
  2347                                  
  2348                                  ; 11/03/2015 - 10/07/2015
  2349 00006684 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2349 0000668D 0000000000         
  2350 00006692 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2350 0000669B 0000000000         
  2351 000066A0 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2351 000066A9 0000000000         
  2352 000066AE 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2352 000066B7 000000000000000000-
  2352 000066C0 000000000000000000-
  2352 000066C9 00                 
  2353 000066CA 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2354 000066D1 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2355                                  ;
  2356                                  
  2357                                  ; 27/08/2014
  2358                                  scr_row:
  2359 000066D8 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2360                                  scr_col:
  2361 000066DC 00000000                	dd 0
  2362                                  
  2363                                  ;; 14/08/2015
  2364                                  ;;msgPM:
  2365                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2366                                  msgKVER:
  2367                                  	;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.2 [29/04/2022]", 0
  2368 000066E0 526574726F20554E49-     	db "Retro UNIX 386 v1.1 - Kernel v0.2.1.3 [02/06/2022]", 0
  2368 000066E9 58203338362076312E-
  2368 000066F2 31202D204B65726E65-
  2368 000066FB 6C2076302E322E312E-
  2368 00006704 33205B30322F30362F-
  2368 0000670D 323032325D00       
  2369 00006713 90                      Align 2
  2370                                  
  2371                                  ; 20/08/2014
  2372                                    ; /* This is the default interrupt "handler" :-) */ 
  2373                                    ; Linux v0.12 (head.s)
  2374                                  int_msg:
  2375 00006714 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2375 0000671D 6E7465727275707420-
  2375 00006726 212000             
  2376                                  
  2377 00006729 90                      Align 2  
  2378                                  
  2379                                  ; 21/08/2014
  2380                                  timer_msg:
  2381 0000672A 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2381 00006733 542032306829202120-
  2381 0000673C 54696D657220496E74-
  2381 00006745 657272757074203A20 
  2382                                  tcountstr:
  2383 0000674E 303030303020            	db "00000 "
  2384 00006754 00                      	db 0
  2385                                  
  2386 00006755 90                      Align 2
  2387                                  	; 21/08/2014
  2388                                  exc_msg:
  2389 00006756 435055206578636570-     	db "CPU exception ! "
  2389 0000675F 74696F6E202120     
  2390                                  excnstr: 		; 25/08/2014
  2391 00006766 3F3F68202045495020-     	db "??h", "  EIP : "
  2391 0000676F 3A20               
  2392                                  EIPstr: ; 29/08/2014
  2393 00006771 00<rep Ch>              	times 12 db 0
  2394                                  rtc_msg:
  2395 0000677D 5265616C2054696D65-     	db "Real Time Clock - "
  2395 00006786 20436C6F636B202D20 
  2396                                  datestr:
  2397 0000678F 30302F30302F303030-     	db "00/00/0000"
  2397 00006798 30                 
  2398 00006799 20                      	db " "
  2399                                  daystr:
  2400 0000679A 44415920                	db "DAY "
  2401                                  timestr:	
  2402 0000679E 30303A30303A3030                db "00:00:00"
  2403 000067A6 20                      	db " "
  2404 000067A7 00                      	db 0 
  2405                                  
  2406                                  daytmp:
  2407                                  	; 28/02/2015
  2408 000067A8 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2408 000067B1 4F4E20545545205745-
  2408 000067BA 442054485520465249-
  2408 000067C3 2053415420         
  2409                                  
  2410 000067C8 FF                      ptime_seconds: db 0FFh
  2411                                  
  2412                                  	; 23/02/2015
  2413                                  	; 25/08/2014
  2414                                  ;scounter:
  2415                                  ;	db 5
  2416                                  ;	db 19
  2417                                  
  2418                                  ; 02/01/2022
  2419                                  ; 05/11/2014
  2420                                  ;msg_out_of_memory:
  2421                                  ;	db 	07h, 0Dh, 0Ah
  2422                                  ;       db	'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2423                                  ; 	db	0Dh, 0Ah, 0
  2424                                  	;
  2425                                  setup_error_msg:
  2426 000067C9 0D0A                    	db 0Dh, 0Ah
  2427 000067CB 4469736B2053657475-     	db 'Disk Setup Error!' 
  2427 000067D4 70204572726F7221   
  2428 000067DC 0D0A00                  	db 0Dh, 0Ah,0
  2429                                  
  2430                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2431                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2432                                  ;	  db 0 ; upper left row (for scroll)	
  2433                                  
  2434                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2435                                  ;	  db 24 ; lower right row (for scroll)
  2436                                  
  2437                                  
  2438                                  ; 06/11/2014 (Temporary Data)
  2439                                  ; Memory Information message
  2440                                  ; 14/08/2015
  2441                                  msg_memory_info:
  2442 000067DF 07                      	db	07h
  2443 000067E0 0D0A                    	db	0Dh, 0Ah
  2444                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2445 000067E2 546F74616C206D656D-     	db	"Total memory : "
  2445 000067EB 6F7279203A20       
  2446                                  mem_total_b_str: ; 10 digits
  2447 000067F1 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2447 000067FA 302062797465730D0A 
  2448 00006803 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2448 0000680C 202020202020202020 
  2449                                  mem_total_p_str: ; 7 digits
  2450 00006815 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2450 0000681E 616765730D0A       
  2451 00006824 0D0A                    	db 	0Dh, 0Ah
  2452 00006826 46726565206D656D6F-     	db	"Free memory  : "
  2452 0000682F 727920203A20       
  2453                                  free_mem_b_str:  ; 10 digits
  2454 00006835 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2454 0000683E 3F2062797465730D0A 
  2455 00006847 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2455 00006850 202020202020202020 
  2456                                  free_mem_p_str:  ; 7 digits
  2457 00006859 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2457 00006862 616765730D0A       
  2458 00006868 0D0A00                  	db	0Dh, 0Ah, 0
  2459                                  
  2460                                  dsk_ready_msg:
  2461 0000686B 0D0A                    	db 	0Dh, 0Ah
  2462                                  dsktype:
  2463 0000686D 6664                    	db	'fd'
  2464                                  dskx:
  2465 0000686F 30                      	db	'0'
  2466 00006870 20                      	db	20h
  2467 00006871 697320524541445920-     	db 	'is READY ...'
  2467 0000687A 2E2E2E             
  2468 0000687D 00                      	db 	0
  2469                                  nextline:
  2470 0000687E 0D0A00                  	db 	0Dh, 0Ah, 0
  2471                                  
  2472                                  ; KERNEL - SYSINIT Messages
  2473                                  ; 24/08/2015
  2474                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2475                                  ; 14/07/2013
  2476                                  ;kernel_init_err_msg:
  2477                                  ;	db 0Dh, 0Ah
  2478                                  ;	db 07h
  2479                                  ;	db 'Kernel initialization ERROR !'
  2480                                  ;	db 0Dh, 0Ah, 0 
  2481                                  ; 24/08/2015
  2482                                  ;;; (temporary kernel init message has been removed
  2483                                  ;;;  from 'sys_init' code)
  2484                                  ;kernel_init_ok_msg: 
  2485                                  ;	db 0Dh, 0Ah
  2486                                  ;	db 07h
  2487                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2488                                  ;	db 0Dh, 0Ah
  2489                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2490                                  ;	db 0Dh, 0Ah, 0
  2491                                  panic_msg:
  2492 00006881 0D0A07                  	db 0Dh, 0Ah, 07h
  2493 00006884 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2493 0000688D 726E656C2050616E69-
  2493 00006896 632021             
  2494 00006899 0D0A00                  	db 0Dh, 0Ah, 0
  2495                                  etc_init_err_msg:
  2496 0000689C 0D0A                    	db 0Dh, 0Ah
  2497 0000689E 07                      	db 07h
  2498 0000689F 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2498 000068A8 74632F696E69742021-
  2498 000068B1 3F                 
  2499 000068B2 0D0A00                  	db 0Dh, 0Ah, 0
  2500                                  
  2501                                  ; 10/05/2015
  2502                                  badsys_msg:
  2503 000068B5 0D0A                    	db 0Dh, 0Ah
  2504 000068B7 07                      	db 07h
  2505 000068B8 496E76616C69642053-     	db 'Invalid System Call !'
  2505 000068C1 797374656D2043616C-
  2505 000068CA 6C2021             
  2506 000068CD 0D0A                    	db 0Dh, 0Ah
  2507 000068CF 4541583A20              	db 'EAX: '
  2508                                  bsys_msg_eax:
  2509 000068D4 303030303030303068      	db '00000000h'
  2510 000068DD 0D0A                    	db 0Dh, 0Ah
  2511 000068DF 4549503A20              	db 'EIP: '
  2512                                  bsys_msg_eip:
  2513 000068E4 303030303030303068      	db '00000000h' 
  2514 000068ED 0D0A00                  	db 0Dh, 0Ah, 0
  2515                                  
  2516                                  BSYS_M_SIZE equ $ - badsys_msg
  2517                                  
  2518                                  
  2519                                  align 2
  2520                                  
  2521                                  ; EPOCH Variables
  2522                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2523                                  ; 09/04/2013 epoch variables
  2524                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2525                                  ;
  2526 000068F0 B207                    year: 	dw 1970
  2527                                  ;month: dw 1
  2528                                  ;day: 	dw 1
  2529                                  ;hour: 	dw 0
  2530                                  ;minute: dw 0
  2531                                  ;second: dw 0
  2532                                  ; 02/06/2022
  2533 000068F2 01                      month:	db 1
  2534 000068F3 01                      day:	db 1
  2535 000068F4 01                      hour:	db 1
  2536 000068F5 01                      minute: db 1
  2537 000068F6 01                      second:	db 1
  2538 000068F7 01                      	db 1
  2539                                  
  2540                                  DMonth:
  2541 000068F8 0000                    	dw 0
  2542 000068FA 1F00                    	dw 31
  2543 000068FC 3B00                    	dw 59
  2544 000068FE 5A00                    	dw 90
  2545 00006900 7800                    	dw 120
  2546 00006902 9700                    	dw 151
  2547 00006904 B500                    	dw 181
  2548 00006906 D400                    	dw 212
  2549 00006908 F300                    	dw 243
  2550 0000690A 1101                    	dw 273
  2551 0000690C 3001                    	dw 304
  2552 0000690E 4E01                    	dw 334
  2553                                  
  2554                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
  2555                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2556 00006910 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2557                                  		   ;   1 and 16 MB, max. 3C00h = 15 MB.
  2558 00006912 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2559 00006914 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2560                                  		   ;   between 16 MB and 4 GB.
  2561 00006916 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2562                                  
  2563                                  ; 02/01/2022
  2564                                  KEND:
  2565                                  
  2566 00006918 90<rep 8h>              align 16
  2567                                  
  2568                                  bss_start:
  2569                                  
  2570                                  ABSOLUTE bss_start
  2571                                  
  2572                                  	; 11/03/2015
  2573                                  	; Interrupt Descriptor Table (20/08/2014)
  2574                                  idt:
  2575 00006920 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2576                                  idt_end:
  2577                                  
  2578                                  ;alignb 4
  2579                                  
  2580                                  task_state_segment:
  2581                                  	; 24/03/2015
  2582 00006B20 ????                    tss.link:   resw 1
  2583 00006B22 ????                    	    resw 1
  2584                                  ; tss offset 4	
  2585 00006B24 ????????                tss.esp0:   resd 1
  2586 00006B28 ????                    tss.ss0:    resw 1
  2587 00006B2A ????                    	    resw 1	
  2588 00006B2C ????????                tss.esp1:   resd 1
  2589 00006B30 ????                    tss.ss1:    resw 1
  2590 00006B32 ????                    	    resw 1 	
  2591 00006B34 ????????                tss.esp2:   resd 1
  2592 00006B38 ????                    tss.ss2:    resw 1
  2593 00006B3A ????                    	    resw 1
  2594                                  ; tss offset 28
  2595 00006B3C ????????                tss.CR3:    resd 1
  2596 00006B40 ????????                tss.eip:    resd 1
  2597 00006B44 ????????                tss.eflags: resd 1
  2598                                  ; tss offset 40
  2599 00006B48 ????????                tss.eax:    resd 1		 		
  2600 00006B4C ????????                tss.ecx:    resd 1
  2601 00006B50 ????????                tss.edx:    resd 1
  2602 00006B54 ????????                tss.ebx:    resd 1
  2603 00006B58 ????????                tss.esp:    resd 1
  2604 00006B5C ????????                tss.ebp:    resd 1
  2605 00006B60 ????????                tss.esi:    resd 1
  2606 00006B64 ????????                tss.edi:    resd 1
  2607                                  ; tss offset 72
  2608 00006B68 ????                    tss.ES:     resw 1
  2609 00006B6A ????                    	    resw 1	
  2610 00006B6C ????                    tss.CS:	    resw 1
  2611 00006B6E ????                    	    resw 1
  2612 00006B70 ????                    tss.SS:	    resw 1
  2613 00006B72 ????                    	    resw 1
  2614 00006B74 ????                    tss.DS:	    resw 1
  2615 00006B76 ????                    	    resw 1
  2616 00006B78 ????                    tss.FS:	    resw 1
  2617 00006B7A ????                    	    resw 1
  2618 00006B7C ????                    tss.GS:	    resw 1
  2619 00006B7E ????                    	    resw 1		
  2620 00006B80 ????                    tss.LDTR:   resw 1
  2621 00006B82 ????                    	    resw 1
  2622                                  ; tss offset 100		
  2623 00006B84 ????                    	    resw 1		
  2624 00006B86 ????                    tss.IOPB:   resw 1
  2625                                  ; tss offset 104 
  2626                                  tss_end:
  2627                                  
  2628 00006B88 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2629                                  		  ;   (Physical address = Virtual address)	 	
  2630 00006B8C ????????                memory_size: resd 1 ; memory size in pages
  2631 00006B90 ????????                free_pages:  resd 1 ; number of free pages		
  2632 00006B94 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2633                                  		  ;   first free page search
  2634 00006B98 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2635                                  		  ;   next free page search will be
  2636                                  		  ; stopped after it. (end of M.A.T.)
  2637 00006B9C ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2638                                  		  ; first free page search
  2639                                  		  ;   will be started on it. (for user)
  2640 00006BA0 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2641                                  
  2642                                  ;;;
  2643                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2644                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2645 00006BA4 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2646                                  			  ; NOTE: active page only
  2647 00006BA6 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2648                                  active_page: 
  2649 00006BB6 ??                      ptty: 	     resb 1 	  ; current tty
  2650                                  ; 01/07/2015
  2651 00006BB7 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2652                                  ; 26/10/2015
  2653                                  ; 07/09/2014
  2654 00006BB8 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2655                                  
  2656                                  ; 21/08/2014
  2657 00006BCC ????????                tcount:	     resd 1
  2658                                  
  2659                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2660 00006BD0 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2661                                  
  2662                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2663                                  ; (open mode locks for pseudo TTYs)
  2664                                  ; [ major tty locks (return error in any conflicts) ]
  2665 00006BD4 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2666                                  
  2667                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2668                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2669 00006BE8 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2670                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2671                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2672                                  ;; 0 means serial port is not available 
  2673                                  ;;comprm: ; 25/06/2014
  2674 00006BF2 ??                      com1p:       resb 1  ;;0E3h
  2675 00006BF3 ??                      com2p:       resb 1  ;;0E3h
  2676                                  
  2677                                  ; 17/11/2015
  2678                                  ; request for response (from the terminal)	
  2679 00006BF4 ????                    req_resp:     resw 1 			
  2680                                  ; 07/11/2015
  2681 00006BF6 ??                      ccomport:    resb 1 ; current COM (serial) port
  2682                                  		    ; (0= COM1, 1= COM2)
  2683                                  ; 09/11/2015
  2684 00006BF7 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2685                                  ; 07/11/2015
  2686 00006BF8 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2687 00006BFA ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2688                                  
  2689                                  ; 23/10/2015
  2690                                  ; SERIAL PORTS - COMMUNICATION MODES
  2691                                  ; (Retro UNIX 386 v1 feature only!)
  2692                                  ; 0 - command mode (default/initial mode)
  2693                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2694                                  ;;; communication modes for futre versions:  
  2695                                  ; // 2 - keyboard mode (ascii+scancode input)
  2696                                  ; // 3 - mouse mode
  2697                                  ; // 4 - device control (output) mode
  2698                                  ; VALID COMMANDS for current version:
  2699                                  ; 	'LOGIN'
  2700                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2701                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2702                                  ;  Login response: db 0FFh, 'login', 0
  2703                                  ;	 ("login request accepted, wait for login prompt") 
  2704                                  ; When a login requests is received and acknowledged (by
  2705                                  ; serial port interrupt handler (communication procedure),
  2706                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2707                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2708                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2709                                  ; 
  2710                                  ; 'sys connect' system call is used to change communication mode
  2711                                  ; except 'LOGIN' command which is used to start terminal mode
  2712                                  ; by using (COM port) terminal.
  2713                                  
  2714                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2715                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2716                                  ;com1mode:    resb 1 ; communication mode for COM1
  2717                                  ;com1com:     resb 1 ; communication command for COM1
  2718                                  ;com2mode:    resb 1 ; communication mode for COM1
  2719                                  ;com2com      resb 1 ; communication command for COM1
  2720                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2721                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2722                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2723                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2724                                  
  2725                                  ; 22/08/2014 (RTC)
  2726                                  ; (Packed BCD)
  2727 00006BFC ??                      time_seconds: resb 1
  2728 00006BFD ??                      time_minutes: resb 1
  2729 00006BFE ??                      time_hours:   resb 1
  2730 00006BFF ??                      date_wday:    resb 1
  2731 00006C00 ??                      date_day:     resb 1
  2732 00006C01 ??                      date_month:   resb 1			
  2733 00006C02 ??                      date_year:    resb 1
  2734 00006C03 ??                      date_century: resb 1
  2735                                  
  2736                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2737                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2738                              <1> ; Last Modification: 10/07/2015
  2739                              <1> ;	(Unnitialized Disk Parameters Data section for 'DISKIO.INC') 
  2740                              <1> ;
  2741                              <1> ; *****************************************************************************
  2742                              <1> 
  2743                              <1> alignb 2
  2744                              <1> 
  2745                              <1> ;----------------------------------------
  2746                              <1> ;	TIMER DATA AREA 		:
  2747                              <1> ;----------------------------------------
  2748                              <1> 
  2749                              <1> TIMER_LH:	; 16/02/205
  2750 00006C04 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2751 00006C06 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2752 00006C08 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2753                              <1> 
  2754                              <1> ;----------------------------------------
  2755                              <1> ;	DISKETTE DATA AREAS		:
  2756                              <1> ;----------------------------------------
  2757                              <1> 
  2758 00006C09 ??                  <1> SEEK_STATUS:	resb	1
  2759 00006C0A ??                  <1> MOTOR_STATUS:	resb	1
  2760 00006C0B ??                  <1> MOTOR_COUNT:	resb	1
  2761 00006C0C ??                  <1> DSKETTE_STATUS:	resb	1
  2762 00006C0D ??????????????      <1> NEC_STATUS:	resb	7
  2763                              <1> 
  2764                              <1> ;----------------------------------------
  2765                              <1> ;	ADDITIONAL MEDIA DATA		:
  2766                              <1> ;----------------------------------------
  2767                              <1> 
  2768 00006C14 ??                  <1> LASTRATE:	resb 	1
  2769 00006C15 ??                  <1> HF_STATUS:	resb 	1
  2770 00006C16 ??                  <1> HF_ERROR:	resb 	1
  2771 00006C17 ??                  <1> HF_INT_FLAG:	resb 	1
  2772 00006C18 ??                  <1> HF_CNTRL:	resb 	1
  2773 00006C19 ????????            <1> DSK_STATE:	resb 	4
  2774 00006C1D ????                <1> DSK_TRK:	resb 	2
  2775                              <1> 
  2776                              <1> ;----------------------------------------
  2777                              <1> ;	FIXED DISK DATA AREAS		:
  2778                              <1> ;----------------------------------------
  2779                              <1> 
  2780 00006C1F ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2781 00006C20 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2782 00006C21 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2783                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2784                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2785                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2786                              <1> 
  2787 00006C22 ????                <1> alignb 4
  2788                              <1> 
  2789                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2790                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2791                              <1> HF_TBL_VEC: ; 22/12/2014	
  2792 00006C24 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2793 00006C28 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2794 00006C2C ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2795 00006C30 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2796                              <1> 
  2797                              <1> ; 03/01/2015
  2798 00006C34 ??                  <1> LBAMode:     	resb	1
  2799                              <1> 
  2800                              <1> ; *****************************************************************************
  2737                                  
  2738                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2739                                  
  2740                                  ;alignb 2
  2741                                  
  2742                                  ; 02/01/2022
  2743                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2744                                  
  2745                                  ; 24/12/2021
  2746                                  ; (memory page swap parameters are disabled as temporary)
  2747                                  ;
  2748                                  ;; Memory (swap) Data (11/03/2015)
  2749                                  ; 09/03/2015
  2750                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2751                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2752                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2753                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2754                                  ;swpd_next:  resd 1 ; next free page block
  2755                                  ;swpd_last:  resd 1 ; last swap page block	
  2756                                  	
  2757 00006C35 ??????                  alignb 4
  2758                                  
  2759                                  ; 10/07/2015
  2760                                  ; 28/08/2014
  2761 00006C38 ????????                error_code:	resd 1
  2762                                  ; 29/08/2014
  2763 00006C3C ????????                FaultOffset: 	resd 1
  2764                                  ; 21/09/2015
  2765 00006C40 ????????                PF_Count:	resd 1	; total page fault count
  2766                                  		       	; (for debugging - page fault analyze)
  2767                                  		 	; 'page _fault_handler' (memory.inc)
  2768                                  			; 'sysgeterr' (u9.s)
  2769                                  ; 26/02/2022
  2770 00006C44 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2771                                  			;  for a system call in next retro unix 386 version)
  2772                                  			; -2 ticks per second-
  2773                                  ;; 21/08/2015
  2774                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2775                                  
  2776                                  ; 02/01/2022
  2777                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2778                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYSX.INC (ux.s)
  2779                              <1> ; Last Modification: 26/02/2022
  2780                              <1> ; ----------------------------------------------------------------------------
  2781                              <1> ; Retro UNIX 386 v1 Kernel - ux.s
  2782                              <1> ; Last Modification: 15/05/2022
  2783                              <1> ;
  2784                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2785                              <1> ; (Modified from 
  2786                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2787                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2788                              <1> ; ----------------------------------------------------------------------------
  2789                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2790                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2791                              <1> ; <Bell Laboratories (17/3/1972)>
  2792                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2793                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2794                              <1> ; ****************************************************************************
  2795                              <1> ; 04/12/2015
  2796                              <1> 
  2797                              <1> alignb 2
  2798                              <1> 
  2799                              <1> inode:
  2800                              <1> 	; 11/03/2013. 
  2801                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2802                              <1> 	;i.
  2803                              <1> 
  2804 00006C48 ????                <1> 	i.flgs:	 resw 1
  2805 00006C4A ??                  <1> 	i.nlks:	 resb 1
  2806 00006C4B ??                  <1> 	i.uid:	 resb 1
  2807 00006C4C ????                <1>         i.size:  resw 1 ; size
  2808 00006C4E <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2809 00006C5E ????????            <1> 	i.ctim:	 resd 1
  2810 00006C62 ????????            <1> 	i.mtim:	 resd 1
  2811 00006C66 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2812                              <1> 
  2813                              <1> I_SIZE	equ $ - inode 
  2814                              <1> 
  2815                              <1> process:
  2816                              <1> 	; 26/02/2022
  2817                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1) 
  2818                              <1> 	; 06/05/2015
  2819                              <1> 	; 11/03/2013 - 05/02/2014
  2820                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2821                              <1> 	;p.
  2822                              <1> 	
  2823 00006C68 <res 20h>           <1>         p.pid:   resw nproc
  2824 00006C88 <res 20h>           <1>         p.ppid:  resw nproc
  2825                              <1> 	;p.break: resw nproc ; 12/01/2022 (p.break is not used)
  2826 00006CA8 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2827                              <1> 	; 26/02/2022 (p.waitc is not used)
  2828                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2829 00006CB8 <res 10h>           <1> 	p.link:	 resb nproc
  2830 00006CC8 <res 10h>           <1> 	p.stat:	 resb nproc
  2831                              <1> 
  2832                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2833 00006CD8 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2834                              <1> 			    ; 'user' structure	
  2835                              <1> 
  2836                              <1> P_SIZE	equ $ - process
  2837                              <1> 
  2838                              <1> ; fsp table (original UNIX v1)
  2839                              <1> ;
  2840                              <1> ;Entry
  2841                              <1> ;          15                                      0
  2842                              <1> ;  1     |---|---------------------------------------|
  2843                              <1> ;        |r/w|       i-number of open file           |
  2844                              <1> ;        |---|---------------------------------------| 
  2845                              <1> ;        |               device number               |
  2846                              <1> ;        |-------------------------------------------|
  2847                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2848                              <1> ;        |-------------------------------------------| 
  2849                              <1> ;        |  flag that says    | number of processes  |
  2850                              <1> ;        |   file deleted     | that have file open  |
  2851                              <1> ;        |-------------------------------------------| 
  2852                              <1> ;  2     |                                           |
  2853                              <1> ;        |-------------------------------------------| 
  2854                              <1> ;        |                                           |
  2855                              <1> ;        |-------------------------------------------|
  2856                              <1> ;        |                                           |
  2857                              <1> ;        |-------------------------------------------|
  2858                              <1> ;        |                                           |
  2859                              <1> ;        |-------------------------------------------| 
  2860                              <1> ;  3     |                                           | 
  2861                              <1> ;        |                                           |  
  2862                              <1> ;
  2863                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2864                              <1> 
  2865                              <1> ; 15/04/2015
  2866 00006D18 <res 1F4h>          <1> fsp:	 resb nfiles*10 ; 11/05/2015 (8 -> 10)
  2867 00006F0C <res 20h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2868 00006F2C ????                <1> ii:	 resw 1
  2869                              <1> ;idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2870                              <1> ;cdev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2871                              <1> ; 11/01/2022
  2872 00006F2E ??                  <1> idev:	 resb 1
  2873 00006F2F ??                  <1> cdev:	 resb 1
  2874                              <1> ; 18/05/2015
  2875                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2876                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2877                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2878                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2879                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2880                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2881                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2882                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2883                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2884                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2885                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2886 00006F30 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2887                              <1> 	        ; as above, for physical drives numbers in following table
  2888 00006F31 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2889                              <1> ; 15/04/2015
  2890 00006F32 ??                  <1> active:	 resb 1 
  2891 00006F33 ??                  <1> 	 resb 1 ; 09/06/2015
  2892 00006F34 ????                <1> mnti:	 resw 1
  2893 00006F36 ????                <1> mntp:	 resw 1 ; 15/05/2022 ; (parent dir inumber of [mnti])
  2894 00006F38 ????                <1> mpid:	 resw 1
  2895 00006F3A ????                <1> rootdir: resw 1
  2896                              <1> ; 14/02/2014
  2897                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2898                              <1> ;		      Single level run queue
  2899                              <1> ;		      (in order to solve sleep/wakeup lock)
  2900 00006F3C ????                <1> runq:	 resw 1
  2901 00006F3E ??                  <1> imod:	 resb 1
  2902 00006F3F ??                  <1> smod:	 resb 1
  2903 00006F40 ??                  <1> mmod:	 resb 1
  2904 00006F41 ??                  <1> sysflg:	 resb 1
  2905                              <1> 
  2906 00006F42 ????                <1> alignb 4
  2907                              <1> 
  2908                              <1> user:
  2909                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2910                              <1> 	; 04/12/2015 
  2911                              <1> 	; 18/10/2015
  2912                              <1> 	; 12/10/2015
  2913                              <1> 	; 21/09/2015
  2914                              <1> 	; 24/07/2015
  2915                              <1> 	; 16/06/2015
  2916                              <1> 	; 09/06/2015
  2917                              <1> 	; 11/05/2015
  2918                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2919                              <1> 	; 10/10/2013
  2920                              <1> 	; 11/03/2013. 
  2921                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2922                              <1> 	;u.
  2923                              <1> 
  2924 00006F44 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2925 00006F48 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2926 00006F4C ????????            <1> 	u.r0:	  resd 1 ; eax
  2927 00006F50 ????                <1> 	u.cdir:	  resw 1
  2928 00006F52 <res Ah>            <1> 	u.fp:	  resb 10
  2929 00006F5C ????????            <1> 	u.fofp:	  resd 1
  2930 00006F60 ????????            <1> 	u.dirp:	  resd 1
  2931 00006F64 ????????            <1> 	u.namep:  resd 1
  2932 00006F68 ????????            <1> 	u.off:	  resd 1
  2933 00006F6C ????????            <1> 	u.base:	  resd 1
  2934 00006F70 ????????            <1> 	u.count:  resd 1
  2935 00006F74 ????????            <1> 	u.nread:  resd 1
  2936 00006F78 ????????            <1> 	u.break:  resd 1 ; break
  2937 00006F7C ????                <1> 	u.ttyp:	  resw 1 
  2938 00006F7E <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  2939                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2940 00006F8E ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2941 00006F8F ??                  <1> 	u.pri:	  resb 1 ; 
  2942 00006F90 ????                <1> 	u.intr:	  resw 1
  2943 00006F92 ????                <1> 	u.quit:	  resw 1
  2944                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2945 00006F94 ????                <1> 	u.ilgins: resw 1
  2946                              <1> 	;u.cdrv:  resw 1 ; cdev
  2947 00006F96 ??                  <1> 	u.cdrv:   resb 1 ; 09/01/2022
  2948 00006F97 ??                  <1> 		  resb 1 ; 09/01/2022 (dword alignment)
  2949 00006F98 ??                  <1> 	u.uid:	  resb 1 ; uid
  2950 00006F99 ??                  <1> 	u.ruid:	  resb 1
  2951 00006F9A ??                  <1> 	u.bsys:	  resb 1
  2952 00006F9B ??                  <1> 	u.uno:	  resb 1
  2953 00006F9C ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2954                              <1> 	; tty number (rtty, rcvt, wtty)
  2955 00006FA0 ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2956                              <1> 	; last error number
  2957 00006FA1 ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2958                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2959 00006FA5 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2960 00006FA9 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2961 00006FAD ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2962 00006FB1 ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2963                              <1> 	;u.pncount: resw 1 
  2964                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2965                              <1> 	;u.pnbase:  resd 1 
  2966                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2967                              <1> 			 ; 09/06/2015
  2968 00006FB3 ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2969 00006FB4 ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2970                              <1> 			 ; 24/07/2015 - 24/06/2015
  2971                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2972                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2973                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2974                              <1>  			 ; 24/06/2015	  	
  2975                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2976                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2977                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2978 00006FB5 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2979                              <1> 
  2980 00006FB9 ??????              <1> alignb 4
  2981                              <1> 
  2982                              <1> U_SIZE	equ $ - user
  2983                              <1> 
  2984                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2985 00006FBC ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2986 00006FC0 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2987 00006FC4 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2988 00006FC8 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2989                              <1> ;argc:	resw 1	; argument count for 'sysexec'
  2990 00006FCA ??                  <1> argc:	resb 1	; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2991 00006FCB ??                  <1> 	resb 1 
  2992 00006FCC ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  2993                              <1> 
  2994                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  2995                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  2996 00006FD0 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  2997 00006FD1 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  2998 00006FD2 ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  2999 00006FD3 ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  3000                              <1> 
  3001                              <1> ;alignb 4
  3002                              <1> 
  3003                              <1> ; 22/08/2015
  3004 00006FD4 <res C30h>          <1> buffer: resb nbuf * 520
  3005                              <1> 
  3006 00007C04 ????????????????    <1> sb0:	resd 2
  3007                              <1> ;s:
  3008                              <1> ; (root disk) super block buffer
  3009                              <1> systm:
  3010                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  3011                              <1> 	; 11/03/2013. 
  3012                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  3013                              <1> 	;s.
  3014                              <1> 
  3015 00007C0C ????                <1> 	resw 1
  3016 00007C0E <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  3017 00007D76 ????                <1> 	resw 1
  3018 00007D78 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  3019                              <1> eofitab equ $ - systm ; 11/02/2022 (end of inode table)
  3020 00007D98 ????????            <1> 	s.time:	 resd 1
  3021 00007D9C ????????            <1> 	s.syst:	 resd 1
  3022 00007DA0 ????????            <1>         s.wait_: resd 1 ; wait
  3023 00007DA4 ????????            <1> 	s.idlet: resd 1
  3024 00007DA8 ????????            <1> 	s.chrgt: resd 1
  3025 00007DAC ????                <1> 	s.drerr: resw 1
  3026                              <1> 
  3027                              <1> S_SIZE	equ $ - systm
  3028                              <1> 
  3029 00007DAE <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  3030                              <1> 
  3031 00007E0C ????????????????    <1> sb1:	resd 2
  3032                              <1> ; (mounted disk) super block buffer
  3033                              <1> mount:	
  3034 00007E14 <res 200h>          <1> 	resb 512  ; 03/06/2015
  3035                              <1> 
  3036                              <1> ;/ ux -- unix
  3037                              <1> ;
  3038                              <1> ;systm:
  3039                              <1> ;
  3040                              <1> ;	.=.+2
  3041                              <1> ;	.=.+128.
  3042                              <1> ;	.=.+2
  3043                              <1> ;	.=.+64.
  3044                              <1> ;	s.time: .=.+4
  3045                              <1> ;	s.syst: .=.+4
  3046                              <1> ;	s.wait: .=.+4
  3047                              <1> ;	s.idlet:.=.+4
  3048                              <1> ;	s.chrgt:.=.+4
  3049                              <1> ;	s.drerr:.=.+2
  3050                              <1> ;inode:
  3051                              <1> ;	i.flgs: .=.+2
  3052                              <1> ;	i.nlks: .=.+1
  3053                              <1> ;	i.uid:  .=.+1
  3054                              <1> ;	i.size: .=.+2
  3055                              <1> ;	i.dskp: .=.+16.
  3056                              <1> ;	i.ctim: .=.+4
  3057                              <1> ;	i.mtim: .=.+4
  3058                              <1> ;	. = inode+32.
  3059                              <1> ;mount:	.=.+1024.
  3060                              <1> ;proc:
  3061                              <1> ;	p.pid:  .=.+[2*nproc]
  3062                              <1> ;	p.dska: .=.+[2*nproc]
  3063                              <1> ;	p.ppid: .=.+[2*nproc]
  3064                              <1> ;	p.break:.=.+[2*nproc]
  3065                              <1> ;	p.link: .=.+nproc
  3066                              <1> ;	p.stat: .=.+nproc
  3067                              <1> ;tty:
  3068                              <1> ;	. = .+[ntty*8.]
  3069                              <1> ;fsp:	.=.+[nfiles*8.]
  3070                              <1> ;bufp:	.=.+[nbuf*2]+6
  3071                              <1> ;sb0:	.=.+8
  3072                              <1> ;sb1:	.=.+8
  3073                              <1> ;swp:	.=.+8
  3074                              <1> ;ii:	.=.+2
  3075                              <1> ;idev:	.=.+2
  3076                              <1> ;cdev:	.=.+2
  3077                              <1> ;deverr: .=.+12.
  3078                              <1> ;active: .=.+2
  3079                              <1> ;rfap:	.=.+2
  3080                              <1> ;rkap:	.=.+2
  3081                              <1> ;tcap:	.=.+2
  3082                              <1> ;tcstate:.=.+2
  3083                              <1> ;tcerrc: .=.+2
  3084                              <1> ;mnti:	.=.+2
  3085                              <1> ;mntd:	.=.+2
  3086                              <1> ;mpid:	.=.+2
  3087                              <1> ;clockp: .=.+2
  3088                              <1> ;rootdir:.=.+2
  3089                              <1> ;toutt:	.=.+16.
  3090                              <1> ;touts: .=.+32.
  3091                              <1> ;runq:	.=.+6
  3092                              <1> ;
  3093                              <1> ;wlist:	.=.+40.
  3094                              <1> ;cc:	.=.+30.
  3095                              <1> ;cf:	.=.+31.
  3096                              <1> ;cl:	.=.+31.
  3097                              <1> ;clist:	.=.+510.
  3098                              <1> ;imod:	.=.+1
  3099                              <1> ;smod:	.=.+1
  3100                              <1> ;mmod:	.=.+1
  3101                              <1> ;uquant: .=.+1
  3102                              <1> ;sysflg: .=.+1
  3103                              <1> ;pptiflg:.=.+1
  3104                              <1> ;ttyoch: .=.+1
  3105                              <1> ; .even
  3106                              <1> ; .=.+100.; sstack:
  3107                              <1> ;buffer: .=.+[ntty*140.]
  3108                              <1> ;	.=.+[nbuf*520.]
  3109                              <1> ;
  3110                              <1> ; . = core-64.
  3111                              <1> ;user:
  3112                              <1> ;	u.sp:    .=.+2
  3113                              <1> ;	u.usp:   .=.+2
  3114                              <1> ;	u.r0:    .=.+2
  3115                              <1> ;	u.cdir:  .=.+2
  3116                              <1> ;	u.fp:    .=.+10.
  3117                              <1> ;	u.fofp:  .=.+2
  3118                              <1> ;	u.dirp:  .=.+2
  3119                              <1> ;	u.namep: .=.+2
  3120                              <1> ;	u.off:   .=.+2
  3121                              <1> ;	u.base:  .=.+2
  3122                              <1> ;	u.count: .=.+2
  3123                              <1> ;	u.nread: .=.+2
  3124                              <1> ;	u.break: .=.+2
  3125                              <1> ;	u.ttyp:  .=.+2
  3126                              <1> ;	u.dirbuf:.=.+10.
  3127                              <1> ;	u.pri:   .=.+2
  3128                              <1> ;	u.intr:  .=.+2
  3129                              <1> ;	u.quit:  .=.+2
  3130                              <1> ;	u.emt:   .=.+2
  3131                              <1> ;	u.ilgins:.=.+2
  3132                              <1> ;	u.cdev:  .=.+2
  3133                              <1> ;	u.uid:   .=.+1
  3134                              <1> ;	u.ruid:  .=.+1
  3135                              <1> ;	u.bsys:  .=.+1
  3136                              <1> ;	u.uno:   .=.+1
  3137                              <1> ;. = core
  2778                                  
  2779                                  ; 27/12/2021
  2780                                  ;buffer: resb (nbuf*520)
  2781                                  
  2782                                  bss_end:
  2783                                  
  2784                                  ; 02/01/2022
  2785                                  BSS_SIZE equ bss_end - bss_start
  2786                                  
  2787                                  ; 27/12/2013
  2788                                  _end:  ; end of kernel code (and read only data, just before bss)
