     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.0.20
     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: 14/06/2022 ] ; 2022 modification (previous: 09/05/2022)
    13                                  ;
    14                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    15                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    16                                  ; <Bell Laboratories (17/3/1972)>
    17                                  ; <Preliminary Release of UNIX Implementation Document>
    18                                  ;
    19                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    20                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    21                                  ;
    22                                  ; ****************************************************************************
    23                                  ; 15/05/2022 - 02/06/2022 - 13/06/2022 (v0.2.0.20)
    24                                  ; 04/02/2016 (v0.2.0.17) - 29/04/2022 (v0.2.0.18) - 09/05/2022 (v0.2.0.19)
    25                                  
    26                                  ; Assembler: NASM 2.15
    27                                  ;	nasm unix386.s -l unix386.lst -o unix386 -Z error.txt
    28                                  
    29                                  ; 24/12/2013
    30                                  
    31                                  ; Entering protected mode:
    32                                  ; Derived from 'simple_asm.txt' source code file and 
    33                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    34                                  ; (gregor.brunmar@home.se)
    35                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    36                                  ;
    37                                  
    38                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    39                                  ; by Michael Chourdakis (2009) 
    40                                  ; http://www.codeproject.com/Articles/45788/
    41                                  ; http://www.michaelchourdakis.com
    42                                  ;
    43                                  
    44                                  ; Global Descriptor Table:
    45                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    46                                  ; by Linus Torvalds (1991-1992)
    47                                  ;
    48                                  
    49                                  KLOAD	equ 10000h ; Kernel loading address
    50                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h 
    51                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    52                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    53                                  ; 19/03/2015
    54                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    55                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    56                                  ; 24/03/2015
    57                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    58                                  ; 19/03/2015
    59                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    60                                  		     ; (at the end of the 1st 4MB)
    61                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    62                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    63                                  
    64                                  ; 27/12/2013
    65                                  KEND    equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    66                                  
    67                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    68                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    69                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    70                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    71                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    72                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    73                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    74                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    75                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    76                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    77                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    78                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    79                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    80                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    81                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    82                                  ;----------------------------------------
    83                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    84                                  ;-----------------------------------------------------------------------------
    85                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
    86                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
    87                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
    88                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
    89                                  
    90                                  ; Memory Allocation Table Address
    91                                  ; 05/11/2014
    92                                  ; 31/10/2014
    93                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
    94                                  					; the 1st 1 MB memory space.
    95                                  					; (This address must be aligned
    96                                  					;  on 128 KB boundary, if it will be
    97                                  					;  changed later.)
    98                                  					; ((lower 17 bits of 32 bit M.A.T.
    99                                  					;   address must be ZERO)).
   100                                  					; ((((Reason: 32 bit allocation 
   101                                  					;     instructions, dword steps)))
   102                                  					; (((byte >> 12 --> page >> 5)))  
   103                                  ;04/11/2014	
   104                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   105                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   106                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   107                                  ;
   108                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   109                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   110                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   111                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   112                                  
   113                                  ; 17/02/2015 (unix386.s)
   114                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   115                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   116                                  ;
   117                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   118                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   119                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   120                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   121                                  
   122                                  
   123                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   124                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   125                                  ;
   126                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   127                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   128                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   129                                  		      ; otherwise it is standard FDPT with physical values 	
   130                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   131                                  		      ; (obsolete for IDE/ATA drives)
   132                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   133                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   134                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   135                                  			; Bit 4 : Reserved. Always 0
   136                                  			; Bit 3 : Set to 1 if more than 8 heads
   137                                  			; Bit 2-0 : Reserved. Alsways 0
   138                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   139                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   140                                  
   141                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   142                                  ; (11 bytes long) will be used by diskette handler/bios
   143                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   144                                  
   145                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   146                                  
   147                                  [ORG 0] 
   148                                  	; 12/11/2014
   149                                  	; Save boot drive number (that is default root drive)
   150 00000000 8816[8A67]              	mov	[boot_drv], dl ; physical drv number
   151                                  
   152                                  	; Determine installed memory
   153                                  	; 31/10/2014
   154                                  	;
   155 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   156 00000007 CD15                    	int	15h	   ; for large configurations
   157 00000009 7308                    	jnc	short chk_ms
   158 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   159 0000000D CD15                    	int	15h
   160                                  	;	   
   161                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   162                                  	;out	70h, al ; select CMOS register
   163                                  	;in	al, 71h ; read data (1 byte)
   164                                  	;mov	cl, al
   165                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   166                                  	;out	70h, al ; select CMOS register
   167                                  	;in	al, 71h ; read data (1 byte)
   168                                  	;mov	ch, al
   169                                   	;      
   170 0000000F 89C1                    	mov	cx, ax
   171 00000011 31D2                    	xor	dx, dx
   172                                  chk_ms:
   173 00000013 890E[1E6A]              	mov	[mem_1m_1k], cx
   174 00000017 8916[206A]              	mov	[mem_16m_64k], dx
   175                                  	; 05/11/2014
   176                                  	;and	dx, dx
   177                                  	;jz	short L2
   178 0000001B 81F90004                        cmp     cx, 1024
   179 0000001F 7351                    	jnb	short L0
   180                                  		 ; insufficient memory_error	
   181                                  		 ; Minimum 2 MB memory is needed... 
   182                                  	; 05/11/2014
   183                                  	; (real mode error printing)
   184 00000021 FB                      	sti
   185 00000022 BE[3600]                	mov	si, msg_out_of_memory
   186 00000025 BB0700                  	mov	bx, 7
   187 00000028 B40E                    	mov	ah, 0Eh	; write tty
   188                                  oom_1:
   189 0000002A AC                      	lodsb
   190 0000002B 08C0                    	or	al, al
   191 0000002D 7404                    	jz	short oom_2
   192 0000002F CD10                    	int	10h
   193 00000031 EBF7                    	jmp	short oom_1
   194                                  oom_2:
   195 00000033 F4                              hlt
   196 00000034 EBFD                    	jmp	short oom_2
   197                                  
   198                                  ; 04/02/2022
   199                                  ; 05/11/2014
   200                                  msg_out_of_memory:
   201 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   202 00000039 496E73756666696369-             db      'Insufficient memory !'
   202 00000042 656E74206D656D6F72-
   202 0000004B 792021             
   203 0000004E 0D0A                    	db	0Dh, 0Ah
   204                                  _int13h_48h_buffer: 
   205                                  	; 04/02/2022 (Runix Kernel v0.2.0.18, 'diskinit.inc')
   206 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   206 00000059 324D42206D656D6F72-
   206 00000062 79206973206E656564-
   206 0000006B 65642E29           
   207 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   208                                  
   209                                  L0:
   210                                  %include 'diskinit.inc' ; 07/03/2015
   211                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - DISKINIT.INC
   212                              <1> ; Last Modification: 09/05/2022
   213                              <1> 
   214                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   215                              <1> 
   216                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   217                              <1> 
   218                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Runix Kernel v0.2.0.18)
   219                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   220                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   221                              <1> ;L0:
   222                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   223                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   224 00000072 BA7F00              <1> 	mov	dx, 7Fh
   225                              <1> L1:	
   226 00000075 FEC2                <1> 	inc	dl
   227 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   228                              <1> 			; Phoenix EDD v1.1 - EDD v3
   229 00000079 BBAA55              <1> 	mov	bx, 55AAh
   230 0000007C CD13                <1> 	int 	13h
   231 0000007E 721A                <1> 	jc	short L2
   232                              <1> 
   233 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   234 00000084 7514                <1> 	jne	short L2
   235 00000086 FE06[8D67]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   236 0000008A 8816[8C67]          <1>         mov     [last_drv], dl  ; last hard disk number
   237 0000008E BB[1067]            <1> 	mov	bx, hd0_type - 80h
   238 00000091 01D3                <1> 	add	bx, dx	 
   239 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   240                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   241                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   242                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   243                              <1>                          ;            (EDD) ready (DPTE ready)
   244                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   245                              <1>                          ;            (EDD-3)
   246                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   247 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   248 00000098 72DB                <1> 	jb	short L1
   249                              <1> L2:
   250                              <1> 	; 23/11/2014
   251                              <1> 	; 19/11/2014
   252 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   253                              <1> 	; 04/02/2016 (esi -> si)
   254 0000009C BE[8E67]            <1> 	mov	si, fd0_type
   255                              <1> L3:
   256                              <1> 	; 14/01/2015
   257 0000009F 8816[8B67]          <1> 	mov	[drv], dl
   258                              <1> 	;
   259 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   260 000000A5 CD13                <1> 	int	13h	
   261 000000A7 7210                <1> 	jc	short L4
   262                              <1> 		; BL = drive type (for floppy drives)
   263                              <1> 		; DL = number of floppy drives
   264                              <1> 		;		
   265                              <1> 		; ES:DI = Address of DPT from BIOS
   266                              <1> 		;
   267 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   268                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   269                              <1> 	; 14/01/2015
   270 000000AB E8BB01              <1> 	call	set_disk_parms
   271                              <1> 	; 10/12/2014
   272 000000AE 81FE[8E67]          <1> 	cmp	si, fd0_type
   273 000000B2 7705                <1> 	ja	short L4
   274 000000B4 46                  <1> 	inc	si ; fd1_type
   275 000000B5 B201                <1> 	mov	dl, 1
   276 000000B7 EBE6                <1> 	jmp	short L3
   277                              <1> L4:
   278                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   279 000000B9 B27F                <1> 	mov	dl, 7Fh
   280                              <1> 	; 24/12/2014 (Temporary)
   281 000000BB 803E[8D67]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   282                              <1> 	;ja	L10       ; yes, all fixed disk operations
   283                              <1> 			  ; will be performed according to
   284                              <1> 			  ; present EDD specification
   285                              <1> 	; 02/01/2022
   286 000000C0 7603                <1> 	jna	short L5
   287 000000C2 E99100              <1> 	jmp	L10
   288                              <1> L5:
   289 000000C5 FEC2                <1> 	inc 	dl
   290 000000C7 8816[8B67]          <1>         mov     [drv], dl
   291 000000CB 8816[8C67]          <1>         mov     [last_drv], dl ; 14/01/2015
   292 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   293 000000D1 CD13                <1> 	int	13h	; (conventional function)
   294                              <1> 	;jc	L13	; fixed disk drive not ready
   295                              <1> 	; 02/01/2022
   296 000000D3 7303                <1> 	jnc	short L6
   297 000000D5 E98301              <1> 	jmp	L13
   298                              <1> L6:
   299 000000D8 8816[8D67]          <1>         mov     [hdc], dl ; number of drives
   300                              <1> 	;; 14/01/2013
   301                              <1> 	;;push	cx
   302 000000DC E88A01              <1> 	call	set_disk_parms
   303                              <1> 	;;pop	cx
   304                              <1> 	;
   305                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   306 000000DF 8A16[8B67]          <1>         mov     dl, [drv]
   307 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   308 000000E6 80FA80              <1> 	cmp	dl, 80h
   309 000000E9 7603                <1> 	jna	short L7
   310 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   311                              <1> L7:	
   312 000000EE 31C0                <1> 	xor	ax, ax
   313 000000F0 8ED8                <1> 	mov	ds, ax
   314 000000F2 8B37                <1>         mov     si, [bx]
   315 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   316 000000F7 8ED8                <1> 	mov	ds, ax
   317 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   318                              <1> 	;jne	L12 ; invalid FDPT
   319                              <1> 	; 02/01/2022
   320 000000FC 7403                <1> 	je	short L7_8
   321 000000FE E95601              <1> 	jmp	L12
   322                              <1> L7_8:
   323 00000101 BF0000              <1> 	mov	di, HD0_DPT
   324 00000104 80FA80              <1> 	cmp	dl, 80h
   325 00000107 7603                <1> 	jna	short L8
   326 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   327                              <1> L8:
   328                              <1> 	; 30/12/2014
   329 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   330 0000010F 8EC0                <1> 	mov	es, ax
   331                              <1> 	; 24/12/2014
   332 00000111 B90800              <1> 	mov	cx, 8
   333 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   334 00000116 8CC8                <1> 	mov	ax, cs
   335 00000118 8ED8                <1> 	mov	ds, ax
   336                              <1> 	; 02/02/2015
   337 0000011A 8A0E[8B67]          <1>         mov     cl, [drv]
   338 0000011E 88CB                <1> 	mov	bl, cl
   339 00000120 B8F001              <1> 	mov	ax, 1F0h
   340 00000123 80E301              <1> 	and	bl, 1
   341 00000126 7406                <1> 	jz	short L9
   342 00000128 C0E304              <1> 	shl	bl, 4
   343 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   344                              <1> L9:
   345 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   346 0000012F 050602              <1> 	add	ax, 206h
   347 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   348 00000133 88D8                <1> 	mov	al, bl
   349 00000135 04A0                <1> 	add	al, 0A0h
   350 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   351                              <1> 	;
   352 00000138 FE06[8B67]          <1> 	inc	byte [drv]
   353 0000013C BB[1067]            <1> 	mov	bx, hd0_type - 80h
   354 0000013F 01CB                <1> 	add	bx, cx
   355 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   356 00000144 A0[8D67]            <1> 	mov	al, [hdc]
   357 00000147 FEC8                <1> 	dec	al
   358                              <1> 	;jz	L13
   359                              <1> 	; 02/01/2022
   360 00000149 7408                <1> 	jz	short L9_10
   361 0000014B 80FA80              <1> 	cmp	dl, 80h
   362                              <1>         ;jna	L5
   363                              <1> 	;jmp	L13
   364                              <1> 	; 02/01/2022
   365 0000014E 7703                <1> 	ja	short L9_10
   366 00000150 E972FF              <1> 	jmp	L5
   367                              <1> L9_10:
   368 00000153 E90501              <1>         jmp     L13
   369                              <1> L10:
   370 00000156 FEC2                <1> 	inc 	dl
   371                              <1> 	; 25/12/2014
   372 00000158 8816[8B67]          <1> 	mov	[drv], dl
   373 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   374 0000015E CD13                <1> 	int	13h	; (conventional function)
   375                              <1> 	;jc	L13
   376                              <1> 	; 02/01/2022
   377 00000160 72F1                <1> 	jc	short L9_10
   378                              <1> 	; 14/01/2015
   379 00000162 8A16[8B67]          <1> 	mov	dl, [drv]
   380 00000166 52                  <1> 	push	dx
   381 00000167 51                  <1> 	push	cx
   382 00000168 E8FE00              <1> 	call	set_disk_parms
   383 0000016B 59                  <1> 	pop	cx
   384 0000016C 5A                  <1> 	pop	dx
   385                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   386                              <1> 	; 04/02/2016 (esi -> si)
   387                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   388                              <1> 	;		 ; at the '_end' of kernel.
   389                              <1> 	;mov	word [si], 30
   390                              <1> 	; 06/07/2016
   391 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   392                              <1> 	; 09/07/2016
   393 00000170 B81E00              <1> 	mov	ax, 001Eh
   394 00000173 8824                <1> 	mov	[si], ah ; 0
   395 00000175 46                  <1> 	inc	si
   396 00000176 8904                <1> 	mov	word [si], ax
   397                              <1>  	; word [si] = 30
   398                              <1> 	;
   399 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   400 0000017A CD13                <1> 	int	13h
   401                              <1>         ;jc	L13
   402                              <1> 	; 02/01/2022
   403 0000017C 72D5                <1> 	jc	short L9_10
   404                              <1> 	; 04/02/2016 (ebx -> bx)
   405                              <1> 	; 14/01/2015
   406                              <1> 	;sub	bx, bx
   407 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   408 00000180 88D3                <1> 	mov	bl, dl
   409 00000182 80EB80              <1> 	sub	bl, 80h
   410 00000185 81C3[9067]          <1> 	add	bx, hd0_type
   411 00000189 8A07                <1> 	mov 	al, [bx]
   412 0000018B 0C80                <1> 	or	al, 80h
   413 0000018D 8807                <1> 	mov 	[bx], al	
   414 0000018F 81EB[8E67]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   415 00000193 81C3[DA67]          <1> 	add	bx, drv.status
   416 00000197 8807                <1> 	mov	[bx], al
   417                              <1> 	; 04/02/2016 (eax -> ax)
   418 00000199 8B4410              <1> 	mov	ax, [si+16]
   419 0000019C 854412              <1> 	test	ax, [si+18]
   420 0000019F 7413                <1> 	jz	short L10_A0h 
   421                              <1> 			; 'CHS only' disks on EDD system 
   422                              <1> 			;  are reported with ZERO disk size
   423 000001A1 81EB[DA67]          <1> 	sub	bx, drv.status
   424 000001A5 C1E302              <1> 	shl	bx, 2
   425 000001A8 81C3[BE67]          <1> 	add	bx, drv.size ; disk size (in sectors)
   426 000001AC 8907                <1> 	mov	[bx], ax
   427 000001AE 8B4412              <1> 	mov	ax, [si+18]
   428                              <1> 	;mov	[bx], ax
   429                              <1> 	; 02/01/2022 (BugFix)
   430 000001B1 894702              <1> 	mov	[bx+2], ax
   431                              <1> 
   432                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   433                              <1> 	 ; for CHS disks (28/02/2015)
   434                              <1> 	; 30/12/2014
   435 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   436 000001B7 88D0                <1> 	mov	al, dl
   437 000001B9 83E003              <1> 	and 	ax, 3
   438 000001BC C0E005              <1> 	shl	al, 5 ; *32
   439 000001BF 01C7                <1> 	add 	di, ax
   440 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   441 000001C4 8EC0                <1> 	mov	es, ax
   442                              <1> 	;
   443 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   444 000001C8 88CC                <1> 	mov	ah, cl	
   445 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   446 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   447 000001CE AB                  <1> 	stosw		
   448 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   449 000001D1 FEC0                <1> 	inc	al
   450 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   451 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   452 000001D6 AA                  <1> 	stosb
   453 000001D7 8A440C              <1> 	mov	al, [si+12]
   454 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   455 000001DB 31C0                <1>  	xor	ax, ax
   456                              <1> 	;dec	ax	 ; 02/01/2015 
   457 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   458                              <1> 	;xor	al, al	 ; 02/01/2015	
   459 000001DE AA                  <1> 	stosb		 ; reserved
   460 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   461                              <1> 		         ; (do not disable retries, 
   462                              <1> 			 ; more than 8 heads)
   463 000001E1 AA                  <1> 	stosb
   464 000001E2 8B4404              <1> 	mov	ax, [si+4]
   465 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   466                              <1> 	;push	ax	 ; 02/01/2015
   467 000001E6 8A4408              <1> 	mov	al, [si+8]
   468 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   469 000001EA 29C0                <1> 	sub 	ax, ax
   470                              <1> 	;pop	ax	 ; 02/01/2015	
   471 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   472 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   473 000001EF 243F                <1> 	and 	al, 3Fh	
   474 000001F1 AA                  <1> 	stosb
   475                              <1> 	;sub	al, al	 ; checksum
   476                              <1> 	;stosb
   477                              <1> 	;
   478 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   479 000001F5 AD                  <1> 	lodsw
   480 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   481 000001F7 AD                  <1> 	lodsw
   482 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   483                              <1> 	;
   484                              <1> 	; checksum calculation
   485 000001F9 89FE                <1> 	mov	si, di
   486 000001FB 06                  <1> 	push	es
   487 000001FC 1F                  <1> 	pop	ds
   488                              <1> 	;mov	cx, 16
   489 000001FD B90F00              <1> 	mov 	cx, 15
   490 00000200 29CE                <1> 	sub	si, cx
   491 00000202 30E4                <1> 	xor	ah, ah
   492                              <1> 	;del	cl
   493                              <1> L11:		
   494 00000204 AC                  <1> 	lodsb
   495 00000205 00C4                <1> 	add	ah, al
   496 00000207 E2FB                <1> 	loop	L11
   497                              <1> 	;
   498 00000209 88E0                <1> 	mov	al, ah
   499 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   500 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   501                              <1> 	;
   502 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   503 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   504                              <1> 	;
   505                              <1> 	; 23/02/2015
   506 00000210 57                  <1> 	push	di
   507                              <1> 	; ES:DI points to DPTE (FDPTE) location
   508                              <1> 	;mov	cx, 8
   509 00000211 B108                <1> 	mov	cl, 8
   510 00000213 F3A5                <1> 	rep	movsw	
   511                              <1> 	;
   512                              <1> 	; 23/02/2015
   513                              <1> 	; (P)ATA drive and LBA validation
   514                              <1> 	; (invalidating SATA drives and setting
   515                              <1> 	; CHS type I/O for old type fixed disks)
   516 00000215 5B                  <1> 	pop	bx
   517 00000216 8CC8                <1> 	mov	ax, cs
   518 00000218 8ED8                <1> 	mov	ds, ax
   519 0000021A 268B07              <1> 	mov	ax, [es:bx]
   520 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   521 00000220 7418                <1> 	je	short L11a
   522 00000222 3D7001              <1> 	cmp	ax, 170h
   523 00000225 7413                <1> 	je	short L11a
   524                              <1> 	; invalidation 
   525                              <1> 	; (because base port address is not 1F0h or 170h)
   526 00000227 30FF                <1> 	xor	bh, bh
   527 00000229 88D3                <1> 	mov	bl, dl
   528 0000022B 80EB80              <1> 	sub	bl, 80h
   529 0000022E C687[9067]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   530 00000233 808F[DC67]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   531 00000238 EB14                <1> 	jmp	short L11b
   532                              <1> L11a:	
   533                              <1> 	; LBA validation
   534 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   535 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   536 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   537                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   538 00000242 28FF                <1> 	sub	bh, bh
   539 00000244 88D3                <1> 	mov	bl, dl
   540 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   541 00000249 80A7[DC67]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   542                              <1> 				; bit 0 = LBA ready bit
   543                              <1> 	; 'diskio' procedure will check this bit !
   544                              <1> L11b:
   545 0000024E 3A16[8C67]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   546 00000252 7307                <1>         jnb     short L13
   547 00000254 E9FFFE              <1>         jmp     L10
   548                              <1> L12:
   549                              <1> 	; Restore data registers
   550 00000257 8CC8                <1> 	mov	ax, cs
   551 00000259 8ED8                <1> 	mov	ds, ax	
   552                              <1> L13:
   553                              <1> 	; 13/12/2014
   554 0000025B 0E                  <1> 	push	cs
   555 0000025C 07                  <1> 	pop	es
   556                              <1> L14:
   557 0000025D B411                <1> 	mov 	ah, 11h
   558 0000025F CD16                <1> 	int 	16h
   559                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   560                              <1> 	; 02/01/2022
   561 00000261 7465                <1> 	jz	short L16
   562 00000263 B010                <1> 	mov	al, 10h
   563 00000265 CD16                <1> 	int 	16h
   564 00000267 EBF4                <1> 	jmp 	short L14
   565                              <1> L15:
   566                              <1> 
   567                              <1> ; //////
   568                              <1> 
   569                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   570                              <1> %if 0
   571                              <1> 	; 24/11/2014
   572                              <1> 	; 19/11/2014
   573                              <1> 	; 14/11/2014
   574                              <1> 	; Temporary code for disk searching code check
   575                              <1> 	;
   576                              <1> 	; This code will show existing (usable) drives and also
   577                              <1> 	; will show EDD interface support status for hard disks		
   578                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   579                              <1> 	; no need to get it again in protected mode...) 
   580                              <1> 	;	
   581                              <1> 	; 13/11/2014
   582                              <1> 	mov	bx, 7
   583                              <1> 	mov	ah, 0Eh
   584                              <1> 	mov	al, [fd0_type]
   585                              <1> 	and	al, al
   586                              <1> 	jz	short L15a
   587                              <1> 	mov	dl, al
   588                              <1> 	mov	al, 'F'
   589                              <1> 	int 	10h
   590                              <1> 	mov	al, 'D'
   591                              <1> 	int 	10h
   592                              <1> 	mov	al, '0'
   593                              <1> 	int 	10h
   594                              <1> 	mov	al, ' '
   595                              <1> 	int	10h
   596                              <1> 	call	L15c
   597                              <1> 	mov	al, ' '
   598                              <1> 	int	10h
   599                              <1> 	;
   600                              <1> 	mov	al, [fd1_type]
   601                              <1> 	and	al, al
   602                              <1> 	jz	short L15a
   603                              <1> 	mov	dl, al
   604                              <1> 	mov	al, 'F'
   605                              <1> 	int 	10h
   606                              <1> 	mov	al, 'D'
   607                              <1> 	int 	10h
   608                              <1> 	mov	al, '1'
   609                              <1> 	int 	10h
   610                              <1> 	mov	al, ' '
   611                              <1> 	int	10h
   612                              <1> 	call	L15c
   613                              <1> 	mov	al, ' '
   614                              <1> 	int	10h
   615                              <1> 	mov	al, ' '
   616                              <1> 	int	10h
   617                              <1> L15a:
   618                              <1> 	mov	al, [hd0_type]
   619                              <1> 	and	al, al
   620                              <1> 	jz	short L15b
   621                              <1> 	mov	dl, al
   622                              <1> 	mov	al, 'H'
   623                              <1> 	int 	10h
   624                              <1> 	mov	al, 'D'
   625                              <1> 	int 	10h
   626                              <1> 	mov	al, '0'
   627                              <1> 	int 	10h
   628                              <1> 	mov	al, ' '
   629                              <1> 	int 	10h
   630                              <1> 	call	L15c
   631                              <1> 	mov	al, ' '
   632                              <1> 	int	10h
   633                              <1> 	;
   634                              <1> 	mov	al, [hd1_type]
   635                              <1> 	and	al, al
   636                              <1> 	jz	short L15b
   637                              <1> 	mov	dl, al
   638                              <1> 	mov	al, 'H'
   639                              <1> 	int 	10h
   640                              <1> 	mov	al, 'D'
   641                              <1> 	int 	10h
   642                              <1> 	mov	al, '1'
   643                              <1> 	int 	10h
   644                              <1> 	mov	al, ' '
   645                              <1> 	int 	10h
   646                              <1> 	call	L15c
   647                              <1> 	mov	al, ' '
   648                              <1> 	int	10h
   649                              <1> 	;
   650                              <1> 	mov	al, [hd2_type]
   651                              <1> 	and	al, al
   652                              <1> 	jz	short L15b
   653                              <1> 	mov	dl, al
   654                              <1> 	mov	al, 'H'
   655                              <1> 	int 	10h
   656                              <1> 	mov	al, 'D'
   657                              <1> 	int 	10h
   658                              <1> 	mov	al, '2'
   659                              <1> 	int 	10h
   660                              <1> 	mov	al, ' '
   661                              <1> 	int 	10h
   662                              <1> 	call	L15c
   663                              <1> 	mov	al, ' '
   664                              <1> 	int	10h
   665                              <1> 	;
   666                              <1> 	mov	al, [hd3_type]
   667                              <1> 	and	al, al
   668                              <1> 	jz	short L15b
   669                              <1> 	mov	dl, al
   670                              <1> 	mov	al, 'H'
   671                              <1> 	int 	10h
   672                              <1> 	mov	al, 'D'
   673                              <1> 	int 	10h
   674                              <1> 	mov	al, '3'
   675                              <1> 	int 	10h
   676                              <1> 	mov	al, ' '
   677                              <1> 	int 	10h
   678                              <1> 	call	L15c
   679                              <1> 	mov	al, ' '
   680                              <1> 	int	10h
   681                              <1> 	;
   682                              <1> L15b:
   683                              <1> 	mov	al, 0Dh
   684                              <1> 	int 	10h	
   685                              <1> 	mov	al, 0Ah
   686                              <1> 	int 	10h
   687                              <1> 	;;xor	ah, ah
   688                              <1> 	;;int 	16h	
   689                              <1> 	;
   690                              <1>         ;jmp	L16  ; jmp short L16
   691                              <1>         ; 02/01/2022
   692                              <1> 	jmp	short L16
   693                              <1> 	;
   694                              <1> L15c:
   695                              <1> 	mov	dh, dl
   696                              <1> 	shr	dh, 4
   697                              <1> 	add	dh, 30h
   698                              <1> 	and	dl, 15
   699                              <1> 	add	dl, 30h
   700                              <1> 	mov	al, dh
   701                              <1> 	int	10h
   702                              <1> 	mov	al, dl
   703                              <1> 	int	10h
   704                              <1> 	retn
   705                              <1> 	;
   706                              <1> 	; end of temporary code for disk searching code check
   707                              <1> 
   708                              <1> %endif
   709                              <1> 
   710                              <1> ; //////
   711                              <1> 
   712                              <1> set_disk_parms:
   713                              <1> 	; 09/05/2022
   714                              <1> 	;	disksize = cylinders*spt*heads (*)
   715                              <1> 	; (fd0&fd1 drv.size is calculated with total cylinders) 
   716                              <1> 	;
   717                              <1> 	; 04/02/2016 (ebx -> bx)
   718                              <1> 	; 10/07/2015
   719                              <1> 	; 14/01/2015
   720                              <1> 	;push	bx
   721 00000269 28FF                <1> 	sub	bh, bh
   722 0000026B 8A1E[8B67]          <1> 	mov	bl, [drv]
   723 0000026F 80FB80              <1> 	cmp	bl, 80h
   724 00000272 7203                <1> 	jb	short sdp0
   725 00000274 80EB7E              <1> 	sub	bl, 7Eh
   726                              <1> sdp0:	
   727 00000277 81C3[DA67]          <1> 	add	bx, drv.status
   728 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   729                              <1> 	;
   730 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   731 00000280 88CC                <1> 	mov	ah, cl ; 
   732 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   733 00000285 81EB[DA67]          <1> 	sub	bx, drv.status
   734 00000289 D0E3                <1> 	shl	bl, 1
   735 0000028B 81C3[9467]          <1> 	add	bx, drv.cylinders
   736 0000028F 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   737 00000290 8907                <1> 	mov	[bx], ax
   738 00000292 50                  <1> 	push	ax ; ** cylinders
   739 00000293 81EB[9467]          <1> 	sub	bx, drv.cylinders
   740 00000297 81C3[A267]          <1> 	add	bx, drv.heads
   741 0000029B 30E4                <1> 	xor	ah, ah
   742 0000029D 88F0                <1> 	mov	al, dh ; heads
   743 0000029F 40                  <1> 	inc	ax
   744 000002A0 8907                <1> 	mov	[bx], ax
   745 000002A2 81EB[A267]          <1>         sub     bx, drv.heads
   746 000002A6 81C3[B067]          <1>         add     bx, drv.spt
   747 000002AA 30ED                <1> 	xor	ch, ch
   748 000002AC 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   749 000002AF 890F                <1> 	mov	[bx], cx
   750 000002B1 81EB[B067]          <1>         sub     bx, drv.spt
   751 000002B5 D1E3                <1> 	shl	bx, 1
   752 000002B7 81C3[BE67]          <1> 	add	bx, drv.size ; disk size (in sectors)
   753                              <1> 	; LBA size = cylinders * heads * secpertrack
   754 000002BB F7E1                <1> 	mul	cx 
   755 000002BD 89C2                <1> 	mov	dx, ax	; heads*spt					
   756 000002BF 58                  <1> 	pop	ax ; ** cylinders
   757                              <1> 	; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads)
   758                              <1> 	;dec	ax ; 1 cylinder reserved (!?) ; (*)
   759 000002C0 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   760 000002C2 8907                <1> 	mov	[bx], ax
   761 000002C4 895702              <1> 	mov	[bx+2], dx
   762                              <1> 	;
   763                              <1> 	;pop	bx
   764 000002C7 C3                  <1> 	retn
   765                              <1> 
   766                              <1> ;align 2
   767                              <1> 
   768                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   769                              <1> ;heads     :  dw 0, 0, 0, 0, 0, 0
   770                              <1> ;spt       :  dw 0, 0, 0, 0, 0, 0
   771                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   772                              <1> 
   773                              <1> ;last_drv:
   774                              <1> ;	db  0
   775                              <1> ;drv_status:
   776                              <1> ;	db  0,0,0,0,0,0
   777                              <1> ;	db 0
   778                              <1> 
   779                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   780                              <1> 
   781                              <1> L16:
   211                                  
   212                                  	; 10/11/2014
   213 000002C8 FA                           	cli	; Disable interrupts (clear interrupt flag)
   214                                  		; Reset Interrupt MASK Registers (Master&Slave)
   215                                  	;mov	al, 0FFh	; mask off all interrupts
   216                                  	;out	21h, al		; on master PIC (8259)
   217                                  	;jmp 	$+2  ; (delay)
   218                                  	;out	0A1h, al	; on slave PIC (8259)
   219                                  	;
   220                                  	; Disable NMI 
   221 000002C9 B080                    	mov   	al, 80h 
   222 000002CB E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   223                                  	; 23/02/2015
   224 000002CD 90                      	nop			;
   225                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   226                                  				; for preventing unknown state (!?)
   227                                  	;
   228                                   	; 20/08/2014
   229                                  	; Moving the kernel 64 KB back (to physical address 0)
   230                                  	; DS = CS = 1000h
   231                                  	; 05/11/2014
   232 000002CE 31C0                    	xor	ax, ax
   233 000002D0 8EC0                    	mov	es, ax ; ES = 0
   234                                  	;
   235 000002D2 B90040                  	mov	cx, (KEND - KLOAD)/4
   236 000002D5 31F6                    	xor	si, si
   237 000002D7 31FF                    	xor	di, di
   238 000002D9 F366A5                  	rep	movsd
   239                                  	;
   240 000002DC 06                      	push	es ; 0
   241 000002DD 68[E102]                	push	L17
   242 000002E0 CB                      	retf
   243                                  	;
   244                                  L17:
   245                                  	; Turn off the floppy drive motor
   246 000002E1 BAF203                          mov     dx, 3F2h
   247 000002E4 EE                              out     dx, al ; 0 ; 31/12/2013
   248                                  
   249                                  	; Enable access to memory above one megabyte
   250                                  L18:
   251 000002E5 E464                    	in	al, 64h
   252 000002E7 A802                    	test	al, 2
   253 000002E9 75FA                            jnz     short L18
   254 000002EB B0D1                    	mov	al, 0D1h	; Write output port
   255 000002ED E664                    	out	64h, al
   256                                  L19:
   257 000002EF E464                    	in	al, 64h
   258 000002F1 A802                    	test	al, 2
   259 000002F3 75FA                            jnz     short L19
   260 000002F5 B0DF                    	mov	al, 0DFh	; Enable A20 line
   261 000002F7 E660                    	out	60h, al
   262                                  ;L20:
   263                                  	;
   264                                  	; Load global descriptor table register
   265                                  
   266                                          ;mov     ax, cs
   267                                          ;mov     ds, ax
   268                                  
   269 000002F9 2E0F0116[B064]                  lgdt    [cs:gdtd]
   270                                  
   271 000002FF 0F20C0                          mov     eax, cr0
   272                                  	; or 	eax, 1
   273 00000302 40                      	inc     ax
   274 00000303 0F22C0                  	mov     cr0, eax
   275                                  
   276                                  	; Jump to 32 bit code
   277                                  	
   278 00000306 66                      	db 66h 			; Prefix for 32-bit
   279 00000307 EA                      	db 0EAh 		; Opcode for far jump
   280 00000308 [0E030000]              	dd StartPM 		; Offset to start, 32-bit
   281                                  				; (1000h:StartPM = StartPM + 10000h)
   282 0000030C 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   283                                  				; assuming that StartPM resides in code32
   284                                  
   285                                  [BITS 32] 
   286                                  
   287                                  StartPM:
   288                                  	; Kernel Base Address = 0 ; 30/12/2013
   289 0000030E 66B81000                	mov ax, KDATA           ; Save data segment identifier
   290 00000312 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   291 00000314 8EC0                           	mov es, ax              ; Move data segment into ES register
   292 00000316 8EE0                           	mov fs, ax              ; Move data segment into FS register
   293 00000318 8EE8                          	mov gs, ax              ; Move data segment into GS register
   294 0000031A 8ED0                            mov ss, ax              ; Move data segment into SS register
   295 0000031C BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   296                                  
   297                                  clear_bss: ; Clear uninitialized data area
   298                                  	; 11/03/2015
   299 00000321 31C0                    	xor	eax, eax ; 0
   300                                  	;mov	ecx, (bss_end - bss_start)/4
   301                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   302                                  	; 27/02/2022
   303 00000323 B9BB050000              	mov	ecx, BSS_SIZE/4
   304 00000328 BF[306A0000]            	mov	edi, bss_start
   305 0000032D F3AB                    	rep	stosd  	
   306                                  
   307                                  memory_init:
   308                                  	; Initialize memory allocation table and page tables
   309                                  	; 16/11/2014
   310                                  	; 15/11/2014
   311                                  	; 07/11/2014
   312                                  	; 06/11/2014
   313                                  	; 05/11/2014
   314                                  	; 04/11/2014
   315                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   316                                  	;
   317                                  ;	xor	eax, eax
   318                                  ;	xor 	ecx, ecx
   319 0000032F B108                    	mov	cl, 8
   320 00000331 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   321 00000336 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   322                                  				   ; for the first 1 MB memory
   323                                  	;
   324 00000338 668B0D[1E6A0000]        	mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   325                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   326 0000033F 66C1E902                	shr	cx, 2		   ; convert 1 KB count to 4 KB count
   327 00000343 890D[A06C0000]          	mov	[free_pages], ecx
   328 00000349 668B15[206A0000]        	mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   329                                  				   ; between 16 MB and 4 GB.	
   330 00000350 6609D2                  	or	dx, dx
   331 00000353 7413                    	jz	short mi_0
   332                                  	;
   333 00000355 6689D0                  	mov	ax, dx
   334 00000358 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   335 0000035B 0105[A06C0000]          	add	[free_pages], eax
   336 00000361 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   337 00000366 EB07                    	jmp	short mi_1
   338                                  mi_0:
   339 00000368 6689C8                  	mov	ax, cx
   340 0000036B 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB		 
   341                                  mi_1:
   342 0000036F A3[9C6C0000]            	mov	[memory_size], eax ; Total available memory in pages
   343                                  				   ; 1 alloc. tbl. bit = 1 memory page
   344                                  				   ; 32 allocation bits = 32 mem. pages   
   345                                  	;
   346 00000374 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page 	
   347 00000379 C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   348                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   349                                  				   ;  --> x M.A.T. pages, if y = 0
   350 0000037C 66A3[B06C0000]          	mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages		
   351 00000382 C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   352                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   353 00000385 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   354                                  	; Set/Calculate Kernel's Page Directory Address
   355 00000387 81C300001000            	add	ebx, MEM_ALLOC_TBL
   356 0000038D 891D[986C0000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   357                                  				   ; just after the last M.A.T. page
   358                                  	;
   359 00000393 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   360 00000396 A3[A86C0000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   361                                  	;			   ; (allocation status search must be 
   362                                  				   ; stopped after here)	
   363 0000039B 31C0                    	xor	eax, eax
   364 0000039D 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)	
   365 0000039E 6651                    	push	cx
   366 000003A0 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to 
   367                                  				   ; count of 32 allocation bits
   368 000003A3 F3AB                    	rep	stosd
   369 000003A5 6659                    	pop	cx
   370 000003A7 40                      	inc	eax		   ; 0	
   371 000003A8 80E11F                  	and	cl, 31		   ; remain bits
   372 000003AB 7412                    	jz	short mi_4
   373 000003AD 8907                    	mov	[edi], eax	   ; reset	
   374                                  mi_2:
   375 000003AF 0FAB07                  	bts	[edi], eax	   ; 06/11/2014		
   376 000003B2 FEC9                    	dec	cl
   377 000003B4 7404                    	jz	short mi_3
   378 000003B6 FEC0                    	inc	al
   379 000003B8 EBF5                    	jmp	short mi_2
   380                                  mi_3:
   381 000003BA 28C0                    	sub	al, al	   	   ; 0
   382 000003BC 83C704                  	add	edi, 4		   ; 15/11/2014
   383                                  mi_4:
   384 000003BF 6609D2                  	or	dx, dx		  ; check 16M to 4G memory space	
   385 000003C2 7421                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   386                                  	;	
   387 000003C4 B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   388                                  	;	
   389 000003C9 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   390 000003CB 7406                    	jz	short mi_5	  ; jump if EDI points to 
   391                                  				  ;         end of first 16 MB	
   392 000003CD D1E9                    	shr	ecx, 1		  ; convert to dword count
   393 000003CF D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   394 000003D1 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   395                                  				  ; (memory hole under 16 MB)
   396                                  mi_5:
   397 000003D3 6689D1                  	mov	cx, dx		  ; count of 64 KB memory blocks
   398 000003D6 D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   399 000003D8 9C                      	pushf			  ; 16/11/2014		
   400 000003D9 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   401 000003DA F3AB                    	rep	stosd
   402 000003DC 40                      	inc	eax		  ; 0
   403 000003DD 9D                      	popf			  ; 16/11/2014
   404 000003DE 7305                    	jnc	short mi_6
   405 000003E0 6648                    	dec	ax		  ; eax = 0000FFFFh
   406 000003E2 AB                      	stosd
   407 000003E3 6640                    	inc	ax		  ; 0		
   408                                  mi_6:
   409 000003E5 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   410 000003E7 730A                    	jnb	short mi_7	  ; end of memory allocation table
   411                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   412 000003E9 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   413 000003EB 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   414 000003ED D1E9                    	shr	ecx, 1		  ; to dword count 	 		
   415 000003EF D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   416 000003F1 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   417                                  mi_7:
   418                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   419 000003F3 BA00001000              	mov	edx, MEM_ALLOC_TBL
   420                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   421                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   422 000003F8 668B0D[B06C0000]        	mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   423 000003FF 89D7                    	mov	edi, edx
   424 00000401 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   425                                  				  ; byte offset in M.A.T.
   426                                  				  ; (1 M.A.T. byte points to 
   427                                  				  ;	      32768 bytes)
   428                                  				  ; Note: MEM_ALLOC_TBL address 
   429                                  				  ; must be aligned on 128 KB 
   430                                  				  ; boundary!
   431 00000404 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   432                                  	; eax = 0
   433 00000406 290D[A06C0000]          	sub	[free_pages], ecx ; 07/11/2014
   434                                  mi_8:
   435 0000040C 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   436                                  	;dec	bl
   437 0000040F FEC9                    	dec	cl
   438 00000411 7404                    	jz	short mi_9
   439 00000413 FEC0                    	inc	al
   440 00000415 EBF5                    	jmp	short mi_8
   441                                  mi_9:
   442                                  	;
   443                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   444                                  	;		(allocate pages for system page tables)
   445                                  
   446                                  	; edx = MEM_ALLOC_TBL
   447 00000417 8B0D[9C6C0000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   448 0000041D 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)	 	
   449 00000423 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   450                                  				 ; page table count (PDE count)
   451                                  	;
   452 00000426 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   453                                  	;
   454 00000427 41                      	inc	ecx		 ; +1 for kernel page directory	
   455                                  	;
   456 00000428 290D[A06C0000]          	sub	[free_pages], ecx ; 07/11/2014
   457                                  	;
   458 0000042E 8B35[986C0000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   459 00000434 C1EE0C                  	shr	esi, 12		 ; convert to page number
   460                                  mi_10:
   461 00000437 89F0                    	mov	eax, esi	 ; allocation bit offset		 
   462 00000439 89C3                    	mov	ebx, eax
   463 0000043B C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   464 0000043E 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   465                                  				 ;   to align on dword boundary
   466 00000441 83E01F                  	and	eax, 31		 ; set allocation bit position 
   467                                  				 ;  (bit 0 to bit 31)
   468                                  	;
   469 00000444 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   470                                  	;
   471 00000446 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   472                                  	;
   473 00000449 46                      	inc	esi		 ; next page table
   474 0000044A E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   475                                  				 ; (ecx = page table count + 1)		
   476                                  	;
   477 0000044C 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   478                                  	;
   479                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   480                                  	;
   481                                  	; Initialize Kernel's Page Directory
   482 0000044D 8B3D[986C0000]          	mov	edi, [k_page_dir]
   483 00000453 89F8                    	mov	eax, edi
   484 00000455 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   485                                  		     	      ; supervisor + read&write + present
   486 00000457 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)	
   487                                  mi_11:
   488 00000459 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   489                                  			        ; EAX points to next page table
   490 0000045E AB                      	stosd
   491 0000045F E2F8                    	loop	mi_11
   492 00000461 29C0                    	sub	eax, eax	; Empty PDE
   493 00000463 66B90004                	mov	cx, 1024	; Entry count (PGSZ/4)
   494 00000467 29D1                    	sub	ecx, edx
   495 00000469 7402                    	jz	short mi_12
   496 0000046B F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   497                                  	;
   498                                  	; Initialization of Kernel's Page Directory is OK, here.
   499                                  mi_12:
   500                                  	; Initialize Kernel's Page Tables
   501                                  	;
   502                                  	; (EDI points to address of page table 0)
   503                                  	; eax = 0
   504 0000046D 8B0D[9C6C0000]          	mov	ecx, [memory_size] ; memory size in pages
   505 00000473 89CA                    	mov	edx, ecx	; (***)
   506 00000475 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   507                                  			     ; supervisor + read&write + present 	
   508                                  mi_13:
   509 00000477 AB                      	stosd
   510 00000478 0500100000              	add	eax, 4096	
   511 0000047D E2F8                    	loop	mi_13	
   512 0000047F 6681E2FF03              	and	dx, 1023	; (***)
   513 00000484 740B                    	jz	short mi_14
   514 00000486 66B90004                	mov	cx, 1024	
   515 0000048A 6629D1                  	sub	cx, dx		; from dx (<= 1023) to 1024
   516 0000048D 31C0                    	xor	eax, eax
   517 0000048F F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   518                                  				; of the last page table
   519                                  mi_14:
   520                                  	;  Initialization of Kernel's Page Tables is OK, here.
   521                                  	;
   522 00000491 89F8                    	mov	eax, edi	; end of the last page table page
   523                                  			        ; (beginging of user space pages)
   524 00000493 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   525 00000496 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   526                                  				; aligning on dword boundary	
   527                                  	 
   528 00000498 A3[AC6C0000]            	mov	[first_page], eax
   529 0000049D A3[A46C0000]            	mov	[next_page], eax ; The first free page pointer
   530                                  				 ; for user programs
   531                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   532                                  	;
   533                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   534                                  	;
   535                                  	
   536                                  	; Enable paging
   537                                  	;
   538 000004A2 A1[986C0000]                    mov     eax, [k_page_dir]
   539 000004A7 0F22D8                  	mov	cr3, eax
   540 000004AA 0F20C0                  	mov	eax, cr0
   541 000004AD 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   542 000004B2 0F22C0                  	mov	cr0, eax
   543                                          ;jmp    KCODE:StartPMP
   544                                  
   545 000004B5 EA                      	db 0EAh 		; Opcode for far jump
   546 000004B6 [BC040000]                      dd StartPMP		; 32 bit offset
   547 000004BA 0800                    	dw KCODE		; kernel code segment descriptor
   548                                  
   549                                  
   550                                  StartPMP:
   551                                  	; 06/11//2014
   552                                  	; Clear video page 0
   553                                  	;
   554                                  	; Temporary Code
   555                                  	;
   556 000004BC B9E8030000              	mov	ecx, 80*25/2
   557 000004C1 BF00800B00              	mov	edi, 0B8000h
   558 000004C6 31C0                    	xor	eax, eax	; black background, black fore color
   559 000004C8 F3AB                    	rep	stosd
   560                                  	
   561                                  	; 19/08/2014
   562                                  	; Kernel Base Address = 0
   563                                  	; It is mapped to (physically) 0 in the page table.
   564                                  	; So, here is exactly 'StartPMP' address.
   565                                  	;
   566                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   567                                  	;;mov	esi, msgPM
   568                                  	;; 14/08/2015 (kernel version message will appear
   569                                  	;;	       when protected mode and paging is enabled)
   570 000004CA B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   571 000004CC BE[F0670000]            	mov	esi, msgKVER
   572 000004D1 BF00800B00              	mov	edi, 0B8000h ; 27/08/2014
   573                                  	; 20/08/2014
   574 000004D6 E892010000              	call	printk
   575                                  
   576                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   577                                  	; // Set IRQ offsets
   578                                  	;
   579                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   580                                  	;
   581                                  					;; ICW1
   582 000004DB B011                    	mov	al, 11h			; Initialization sequence
   583 000004DD E620                    	out	20h, al			; 	8259A-1
   584                                  	; jmp 	$+2
   585 000004DF E6A0                    	out	0A0h, al		; 	8259A-2
   586                                  					;; ICW2
   587 000004E1 B020                    	mov	al, 20h			; Start of hardware ints (20h)
   588 000004E3 E621                    	out	21h, al			;	for 8259A-1
   589                                  	; jmp 	$+2
   590 000004E5 B028                    	mov	al, 28h			; Start of hardware ints (28h)
   591 000004E7 E6A1                    	out	0A1h, al		; 	for 8259A-2
   592                                  					;
   593 000004E9 B004                    	mov	al, 04h			;; ICW3
   594 000004EB E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   595                                  	; jmp 	$+2
   596 000004ED B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   597 000004EF E6A1                    	out	0A1h, al		;
   598                                  					;; ICW4
   599 000004F1 B001                    	mov	al, 01h	 		;
   600 000004F3 E621                    	out	21h, al			; 	8086 mode, normal EOI	
   601                                  	; jmp 	$+2
   602 000004F5 E6A1                    	out	0A1h, al		;	for both chips.
   603                                  
   604                                  	;mov	al, 0FFh	; mask off all interrupts for now
   605                                  	;out	21h, al
   606                                  	;; jmp 	$+2
   607                                  	;out	0A1h, al
   608                                  
   609                                  	; 02/04/2015
   610                                  	; 26/03/2015 System call (INT 30h) modification
   611                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   612                                  	;
   613                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   614                                  	;  setup_idt:
   615                                  	;
   616                                          ;; 16/02/2015
   617                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   618                                  	; 21/08/2014 (timer_int)
   619 000004F7 BE[BC640000]            	mov	esi, ilist
   620 000004FC 8D3D[306A0000]          	lea	edi, [idt]
   621                                  	; 26/03/2015
   622 00000502 B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   623                                  	; 02/04/2015
   624 00000507 BB00000800              	mov	ebx, 80000h
   625                                  rp_sidt1:
   626 0000050C AD                      	lodsd
   627 0000050D 89C2                    	mov	edx, eax
   628 0000050F 66BA008E                	mov	dx, 8E00h
   629 00000513 6689C3                  	mov	bx, ax
   630 00000516 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   631                                         			        ; /* interrupt gate - dpl=0, present */
   632 00000518 AB                      	stosd	; selector & offset bits 0-15 	
   633 00000519 89D0                    	mov	eax, edx
   634 0000051B AB                      	stosd	; attributes & offset bits 16-23
   635 0000051C E2EE                    	loop	rp_sidt1
   636 0000051E B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   637                                  rp_sidt2:
   638 00000520 AD                      	lodsd
   639 00000521 21C0                    	and	eax, eax
   640 00000523 7413                    	jz	short rp_sidt3
   641 00000525 89C2                    	mov	edx, eax
   642 00000527 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   643 0000052B 6689C3                  	mov	bx, ax
   644 0000052E 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   645 00000530 AB                      	stosd
   646 00000531 89D0                    	mov	eax, edx
   647 00000533 AB                      	stosd
   648 00000534 E2EA                    	loop	rp_sidt2
   649 00000536 EB16                    	jmp	short sidt_OK
   650                                  rp_sidt3:
   651 00000538 B8[90090000]            	mov	eax, ignore_int
   652 0000053D 89C2                    	mov	edx, eax
   653 0000053F 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   654 00000543 6689C3                  	mov	bx, ax
   655 00000546 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   656                                  rp_sidt4:
   657 00000548 AB                      	stosd
   658 00000549 92                      	xchg	eax, edx
   659 0000054A AB                      	stosd
   660 0000054B 92                      	xchg	edx, eax
   661 0000054C E2FA                    	loop	rp_sidt4
   662                                  sidt_OK: 
   663 0000054E 0F011D[B6640000]        	lidt 	[idtd]
   664                                  	;
   665                                  	; TSS descriptor setup ; 24/03/2015
   666 00000555 B8[306C0000]            	mov	eax, task_state_segment
   667 0000055A 66A3[AA640000]          	mov	[gdt_tss0], ax
   668 00000560 C1C010                  	rol	eax, 16
   669 00000563 A2[AC640000]            	mov	[gdt_tss1], al
   670 00000568 8825[AF640000]          	mov	[gdt_tss2], ah
   671 0000056E 66C705[966C0000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   671 00000576 00                 
   672                                  		; 
   673                                  		; IO Map Base address (When this address points
   674                                  		; to end of the TSS, CPU does not use IO port 
   675                                  		; permission bit map for RING 3 IO permissions, 
   676                                  		; access to any IO ports in ring 3 will be forbidden.)
   677                                   		;
   678                                  	;mov	[tss.esp0], esp ; TSS offset 4
   679                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   680 00000577 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   681                                  			 ; occurs (or a system call -software INT- is requested)
   682                                  			 ; while cpu running in ring 3 (in user mode).				
   683                                  			 ; (Kernel stack pointer and segment will be loaded
   684                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   685 0000057B 0F00D8                  	ltr	ax  ; Load task register
   686                                  	;
   687                                  esp0_set0:
   688                                  	; 30/07/2015
   689 0000057E 8B0D[9C6C0000]          	mov 	ecx, [memory_size] ; memory size in pages
   690 00000584 C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   691 00000587 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   692                                  			  ; (kernel mode virtual address)
   693 0000058D 7605                    	jna	short esp0_set1
   694                                  	;
   695                                  	; If available memory > CORE (end of the 1st 4 MB)
   696                                  	; set stack pointer to CORE
   697                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   698                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   699 0000058F B900004000              	mov	ecx, CORE
   700                                  esp0_set1:
   701 00000594 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   702                                  esp0_set_ok:
   703                                  	; 30/07/2015 (**tss.esp0**) 
   704 00000596 8925[346C0000]          	mov	[tss.esp0], esp
   705 0000059C 66C705[386C0000]10-             mov     word [tss.ss0], KDATA
   705 000005A4 00                 
   706                                  	; 14/08/2015
   707                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   708                                  	;
   709                                  	;cli	; Disable interrupts (for CPU)
   710                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   711                                  	;
   712 000005A5 30C0                    	xor	al, al		; Enable all hardware interrupts!
   713 000005A7 E621                    	out	21h, al		; (IBM PC-AT compatibility)
   714 000005A9 EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   715 000005AB E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   716                                  				; (Even if related hardware component
   717                                  				;  does not exist!)
   718                                  	; Enable NMI 
   719 000005AD B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   720 000005AF E670                    	out  	70h, al
   721                                  	; 23/02/2015
   722 000005B1 90                      	nop
   723 000005B2 E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   724                                  				; for preventing unknown state (!?)
   725                                  	;
   726                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   727                                  	;
   728                                  	; 02/09/2014
   729                                  	;xor	bx, bx
   730                                  	;mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   731                                  	; 27/02/2022	
   732 000005B4 31DB                    	xor	ebx, ebx
   733 000005B6 31D2                    	xor	edx, edx
   734 000005B8 B602                    	mov	dh, 2
   735 000005BA E8250F0000              	call	set_cpos
   736                                  	;
   737                                  	; 06/11/2014
   738                                  	; Temporary Code
   739                                  	;
   740 000005BF E89A100000              	call	memory_info
   741                                  	; 14/08/2015
   742                                  	;call getch ; 28/02/2015
   743                                  drv_init:
   744 000005C4 FB                      	sti	; Enable Interrupts 
   745                                  	; 06/02/2015
   746 000005C5 8B15[90670000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   747 000005CB 668B1D[8E670000]        	mov	bx, [fd0_type] ; fd0, fd1
   748                                  	; 22/02/2015
   749 000005D2 6621DB                  	and	bx, bx
   750 000005D5 751B                    	jnz	short di1
   751                                  	;
   752 000005D7 09D2                    	or 	edx, edx
   753 000005D9 7529                    	jnz	short di2
   754                                  	;
   755                                  setup_error:
   756 000005DB BE[D7680000]            	mov 	esi, setup_error_msg
   757                                  psem:	
   758 000005E0 AC                      	lodsb
   759 000005E1 08C0                    	or	al, al
   760                                  	;jz	short haltx ; 22/02/2015
   761 000005E3 7426                    	jz	short di3
   762 000005E5 56                      	push	esi
   763 000005E6 31DB                    	xor	ebx, ebx ; 0
   764                                  			; Video page 0 (bl=0)
   765 000005E8 B407                    	mov	ah, 07h ; Black background, 
   766                                  			; light gray forecolor
   767 000005EA E8EB0D0000              	call	write_tty
   768 000005EF 5E                      	pop	esi
   769 000005F0 EBEE                    	jmp	short psem
   770                                  
   771                                  di1:
   772                                  	; supress 'jmp short T6'
   773                                  	;  (activate fdc motor control code)
   774 000005F2 66C705[EE060000]90-     	mov	word [T5], 9090h ; nop
   774 000005FA 90                 
   775                                  	;
   776                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   777                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   778                                  	;stosw
   779                                  	;mov 	ax, cs
   780                                  	;stosw
   781                                  	;; 16/02/2015
   782                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   783                                  	;
   784 000005FB E8741F0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   785                                  	;
   786 00000600 09D2                    	or	edx, edx
   787 00000602 7407                            jz      short di3
   788                                  di2:
   789 00000604 E8B11F0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   790 00000609 72D0                            jc      short setup_error
   791                                  di3:
   792 0000060B E822100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   793                                  	;
   794 00000610 E8C15D0000              	call	display_disks ; 07/03/2015  (Temporary)
   795                                  ;haltx:
   796                                  	; 14/08/2015
   797                                  	;call	getch ; 22/02/2015
   798 00000615 FB                      	sti	; Enable interrupts (for CPU)
   799                                  	; 14/08/2015
   800                                  	;mov 	ecx, 0FFFFFFFh
   801                                  	; 16/02/2022
   802 00000616 B9FFFF4F00              	mov 	ecx, 04FFFFFh
   803                                  md_info_msg_wait:
   804 0000061B 51                      	push 	ecx
   805 0000061C B001                    	mov	al, 1
   806 0000061E 8A25[C66C0000]          	mov 	ah, [ptty] ; active (current) video page
   807 00000624 E8985A0000              	call	getc_n
   808 00000629 59                      	pop	ecx
   809 0000062A 7502                    	jnz	short md_info_msg_ok
   810 0000062C E2ED                    	loop	md_info_msg_wait
   811                                  md_info_msg_ok:
   812                                  	; 30/06/2015
   813 0000062E E8922C0000              	call	sys_init
   814                                  	;
   815                                  	;jmp 	cpu_reset ; 22/02/2015
   816                                  hang:
   817                                  	; 27/02/2022
   818 00000633 29C0                    	sub	eax, eax
   819                                  _hang: 
   820                                  	; 23/02/2015
   821                                  	;sti			; Enable interrupts
   822 00000635 F4                      	hlt
   823                                  	;
   824                                  	;nop
   825                                  	;; 03/12/2014
   826                                  	;; 28/08/2014
   827                                  	;mov	ah, 11h
   828                                  	;call	getc
   829                                  	;jz      _c8
   830                                  	;
   831                                  	; 23/02/2015
   832                                  	; 06/02/2015
   833                                  	; 07/09/2014
   834 00000636 31DB                    	xor	ebx, ebx
   835 00000638 8A1D[C66C0000]          	mov	bl, [ptty]	; active_page
   836 0000063E 89DE                    	mov	esi, ebx
   837 00000640 66D1E6                  	shl 	si, 1
   838 00000643 81C6[C86C0000]          	add	esi, ttychr
   839 00000649 668B06                  	mov	ax, [esi]
   840                                  	;and	ax, ax
   841                                  	;;jz	short _c8
   842                                  	;jz	short hang
   843                                  	; 27/02/2022
   844 0000064C 21C0                    	and	eax, eax
   845 0000064E 74E5                    	jz	short _hang
   846 00000650 66C7060000              	mov	word [esi], 0
   847 00000655 80FB03                  	cmp	bl, 3		; Video page 3
   848                                  	;jb	short _c8
   849 00000658 72D9                    	jb	short hang
   850                                  	;	
   851                                  	; 02/09/2014
   852 0000065A B40E                    	mov	ah, 0Eh		; Yellow character 
   853                                  				; on black background
   854                                  	; 27/02/2022 (32 bit reg push-pop)
   855                                  	; 07/09/2014
   856                                  nxtl:
   857                                  	;push	bx
   858 0000065C 53                      	push	ebx
   859                                  	;
   860                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   861                                  				; bh = 0 (video mode)
   862                                  				; Retro UNIX 386 v1 - Video Mode 0
   863                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   864 0000065D 50                      	push	eax
   865 0000065E E8770D0000              	call 	write_tty
   866 00000663 58                      	pop	eax
   867                                  	;pop	bx
   868 00000664 5B                      	pop	ebx
   869 00000665 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   870                                  	;jne	short _c8
   871 00000667 75CA                    	jne	short hang
   872 00000669 B00A                    	mov	al, 0Ah		; next line
   873 0000066B EBEF                    	jmp	short nxtl
   874                                  	
   875                                  ;_c8:
   876                                  ;	; 25/08/2014
   877                                  ;	cli				; Disable interrupts
   878                                  ;	mov	al, [scounter + 1]
   879                                  ;	and	al, al
   880                                  ;	jnz	hang
   881                                  ;	call	rtc_p
   882                                  ;	jmp     hang
   883                                  
   884                                  
   885                                  	; 27/08/2014
   886                                  	; 20/08/2014
   887                                  printk:
   888                                          ;mov    edi, [scr_row]
   889                                  pkl:
   890 0000066D AC                      	lodsb
   891 0000066E 08C0                    	or 	al, al
   892 00000670 7404                    	jz	short pkr
   893 00000672 66AB                    	stosw
   894 00000674 EBF7                    	jmp	short pkl
   895                                  pkr:
   896 00000676 C3                      	retn
   897                                  
   898                                  ; 25/07/2015
   899                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   900                                  ; 17/02/2015
   901                                  ; 06/02/2015 (unix386.s)
   902                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   903                                  ;
   904                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   905                                  ;
   906                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   907                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   908                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   909                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   910                                  ;									       :
   911                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   912                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   913                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   914                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   915                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   916                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   917                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   918                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   919                                  ;-------------------------------------------------------------------------------
   920                                  ;
   921                                  
   922                                  timer_int:	; IRQ 0
   923                                  ;int_08h:	; Timer
   924                                  	; 14/10/2015
   925                                  	; Here, we are simulating system call entry (for task switch)
   926                                  	; (If multitasking is enabled, 
   927                                  	; 'clock' procedure may jump to 'sysrelease')
   928 00000677 1E                      	push	ds
   929 00000678 06                      	push	es
   930 00000679 0FA0                    	push	fs
   931 0000067B 0FA8                    	push	gs
   932 0000067D 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   933 0000067E 66B91000                	mov     cx, KDATA
   934 00000682 8ED9                            mov     ds, cx
   935 00000684 8EC1                            mov     es, cx
   936 00000686 8EE1                            mov     fs, cx
   937 00000688 8EE9                            mov     gs, cx
   938                                  	;
   939 0000068A 0F20D9                  	mov	ecx, cr3
   940 0000068D 890D[30070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   941                                  	;
   942 00000693 3B0D[986C0000]          	cmp 	ecx, [k_page_dir]
   943 00000699 741F                    	je	short T3
   944                                  	;
   945                                  	; timer interrupt has been occurred while OS is in user mode
   946 0000069B A3[5C700000]            	mov 	[u.r0], eax
   947 000006A0 89E1                    	mov	ecx, esp
   948 000006A2 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   949 000006A5 890D[54700000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   950 000006AB 8925[58700000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   951                                  	;
   952 000006B1 8B0D[986C0000]          	mov	ecx, [k_page_dir]
   953 000006B7 0F22D9                  	mov	cr3, ecx
   954                                  T3:
   955 000006BA FB                      	sti				; INTERRUPTS BACK ON
   956 000006BB 66FF05[146D0000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   957 000006C2 7507                    	JNZ	short T4		; GO TO TEST_DAY
   958 000006C4 66FF05[166D0000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   959                                  T4:					; TEST_DAY
   960 000006CB 66833D[166D0000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
   961 000006D3 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
   962 000006D5 66813D[146D0000]B0-     	CMP	word [TIMER_LOW],0B0H
   962 000006DD 00                 
   963 000006DE 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
   964                                  
   965                                  ;-----	TIMER HAS GONE 24 HOURS
   966                                  	;;SUB	AX,AX
   967                                  	;MOV	[TIMER_HIGH],AX
   968                                  	;MOV	[TIMER_LOW],AX
   969 000006E0 29C0                    	sub	eax, eax
   970 000006E2 A3[146D0000]            	mov	[TIMER_LH], eax
   971                                  	;	
   972 000006E7 C605[186D0000]01        	MOV	byte [TIMER_OFL],1
   973                                  
   974                                  ;-----	TEST FOR DISKETTE TIME OUT
   975                                  
   976                                  T5:
   977                                  	; 23/12/2014
   978 000006EE EB1D                    	jmp	short T6		; will be replaced with nop, nop
   979                                  					; (9090h) if a floppy disk
   980                                  					; is detected.
   981                                  	;mov	al,[CS:MOTOR_COUNT]
   982 000006F0 A0[1B6D0000]            	mov	al, [MOTOR_COUNT]
   983 000006F5 FEC8                    	dec	al
   984                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
   985 000006F7 A2[1B6D0000]            	mov	[MOTOR_COUNT], al
   986                                  	;mov	[ORG_MOTOR_COUNT], al
   987 000006FC 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
   988 000006FE B0F0                    	mov 	al,0F0h
   989                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
   990 00000700 2005[1A6D0000]          	and	[MOTOR_STATUS], al
   991                                  	;and	[ORG_MOTOR_STATUS], al
   992 00000706 B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
   993                                  					; bit 2 = enable controller
   994                                  					;	1 = normal operation
   995                                  					;	0 = reset	
   996                                  					; bit 0, 1 = drive select
   997                                  					; bit 4-7 = motor running bits 
   998 00000708 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
   999 0000070C EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1000                                  T6:	
  1001                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1002                                  					; TIMER TICK INTERRUPT
  1003                                  	;;inc	word [wait_count] ;;27/02/2015
  1004                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1005                                  	;;;;cli
  1006                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1007 0000070D FF15[28070000]          	call	[x_timer] ; 14/05/2015
  1008                                  T7:
  1009                                  	; 14/10/2015
  1010 00000713 B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1011 00000715 FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1012 00000716 E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1013                                  	;
  1014 00000718 A1[30070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1015 0000071D 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1016                                  	;
  1017 00000720 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1018                                  	;
  1019 00000721 0FA9                    	pop	gs
  1020 00000723 0FA1                    	pop	fs
  1021 00000725 07                      	pop	es
  1022 00000726 1F                      	pop	ds
  1023 00000727 CF                      	iretd	; return from interrupt
  1024                                  
  1025                                  
  1026                                  ; ////////////////
  1027                                  
  1028                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1029                                  x_timer:
  1030 00000728 [34070000]              	dd 	u_timer	; (temporary demo code)	; 14/05/2015
  1031                                  	;dd	clock
  1032                                  
  1033                                  ; 23/02/2022 - Real time clock (digital) output demo (sys emt)
  1034                                  x_rtci:
  1035 0000072C [690A0000]              	dd	rtc_p	; (temporary demo code)	; 23/02/2022
  1036                                  
  1037                                  ; 14/10/2015
  1038 00000730 00000000                cr3reg: dd 0
  1039                                  
  1040                                  	; 06/02/2015
  1041                                  	; 07/09/2014
  1042                                  	; 21/08/2014
  1043                                  u_timer:
  1044                                  	; 27/02/2022
  1045                                  	; 12/02/2022
  1046                                  ;timer_int:	; IRQ 0
  1047                                  	; 06/02/2015
  1048                                  	;push	eax
  1049                                  	;push	edx
  1050                                  	;push	ecx
  1051                                  	;push	ebx
  1052                                  	;push	ds
  1053                                  	;push	es
  1054                                  	;mov	eax, KDATA
  1055                                  	;mov	ds, ax
  1056                                  	;mov	es, ax
  1057 00000734 FF05[DC6C0000]          	inc	dword [tcount]
  1058 0000073A BB[60680000]            	mov	ebx, tcountstr + 4
  1059                                  	;mov	ax, [tcount]
  1060                                  	; 27/02/2022
  1061 0000073F A1[DC6C0000]            	mov	eax, [tcount]
  1062                                  	;mov	ecx, 10
  1063 00000744 31C9                    	xor	ecx, ecx
  1064 00000746 B10A                    	mov	cl, 10
  1065                                  rp_divtcnt:
  1066 00000748 31D2                    	xor	edx, edx
  1067 0000074A F7F1                    	div	ecx
  1068 0000074C 80C230                  	add	dl, 30h
  1069 0000074F 8813                    	mov	[ebx], dl
  1070                                  	;or	ax, ax
  1071                                  	; 27/02/2022
  1072 00000751 09C0                    	or	eax, eax
  1073 00000753 7403                    	jz	short print_lzero
  1074 00000755 4B                      	dec	ebx
  1075 00000756 EBF0                    	jmp	short rp_divtcnt
  1076                                  print_lzero:
  1077 00000758 81FB[5C680000]          	cmp	ebx, tcountstr
  1078 0000075E 7606                    	jna	short print_tcount
  1079 00000760 4B                      	dec	ebx
  1080 00000761 C60330                   	mov	byte [ebx], 30h
  1081 00000764 EBF2                    	jmp	short print_lzero
  1082                                  print_tcount:
  1083 00000766 56                      	push	esi
  1084 00000767 57                      	push	edi
  1085 00000768 BE[38680000]            	mov	esi, timer_msg ; Timer interrupt message
  1086                                  	;; 07/09/2014
  1087                                  	;mov	bx, 1		; Video page 1
  1088                                  	; 12/02/2022
  1089                                  	;mov	bx, 6		; Video page 6
  1090                                  	; 27/02/2022
  1091 0000076D 29DB                    	sub	ebx, ebx
  1092 0000076F B306                    	mov	bl, 6	; Video page 6
  1093                                  ptmsg:
  1094 00000771 AC                      	lodsb
  1095 00000772 08C0                    	or	al, al
  1096 00000774 740D                    	jz	short ptmsg_ok
  1097 00000776 56                      	push	esi
  1098                                  	;push	bx
  1099                                  	; 27/02/2022
  1100 00000777 53                              push	ebx
  1101 00000778 B42F                            mov     ah,  2Fh ; Green background, white forecolor
  1102 0000077A E85B0C0000              	call 	write_tty
  1103                                  	;pop	bx
  1104                                  	; 27/02/2022
  1105 0000077F 5B                      	pop	ebx
  1106 00000780 5E                      	pop	esi
  1107 00000781 EBEE                    	jmp	short ptmsg
  1108                                  	;; 27/08/2014
  1109                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1110                                  	;call	printk
  1111                                  	;
  1112                                  ptmsg_ok:
  1113                                  	; 07/09/2014
  1114                                  	;xor	dx, dx		; column 0, row 0
  1115                                  	; 27/02/2022
  1116 00000783 31D2                    	xor	edx, edx
  1117 00000785 E85A0D0000              	call	set_cpos	; set cursor position to 0,0 
  1118                                  	; 23/02/2015
  1119                                  	; 25/08/2014
  1120                                  	;mov	ebx, scounter		; (seconds counter)
  1121                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1122                                  ;	dec	byte [scounter+1]
  1123                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1124                                  ;	jns	short u_timer_retn
  1125                                  	; 26/02/2015
  1126                                  ;	call	rtc_p
  1127                                  ;	mov	ebx, scounter		; (seconds counter)
  1128                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1129                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1130                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1131                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1132                                  ;	mov	byte [ebx], 5
  1133                                  ;	inc	byte [ebx+1] ; 19
  1134                                  ;;timer_eoi:
  1135                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1136                                  ;;	out	20h, al	; 8259 PORT
  1137                                  	;
  1138                                  ;u_timer_retn:  ; 06/02/2015
  1139 0000078A 5F                      	pop	edi
  1140 0000078B 5E                      	pop	esi
  1141                                  	;pop	es
  1142                                  	;pop	ds
  1143                                  	;pop	ebx
  1144                                  	;pop	ecx
  1145                                  	;pop	edx
  1146                                  	;pop	eax
  1147                                  	;iret
  1148 0000078C C3                      	retn	; 06/02/2015
  1149                                  
  1150                                  	; 28/08/2014
  1151                                  irq0:
  1152 0000078D 6A00                            push 	dword 0
  1153 0000078F EB48                    	jmp	short which_irq
  1154                                  irq1:
  1155 00000791 6A01                            push 	dword 1
  1156 00000793 EB44                    	jmp	short which_irq
  1157                                  irq2:
  1158 00000795 6A02                            push 	dword 2
  1159 00000797 EB40                    	jmp	short which_irq
  1160                                  irq3:
  1161                                  	; 20/11/2015
  1162                                  	; 24/10/2015
  1163 00000799 2EFF15[D6390000]        	call	dword [cs:com2_irq3]
  1164 000007A0 6A03                    	push 	dword 3
  1165 000007A2 EB35                    	jmp	short which_irq
  1166                                  irq4:
  1167                                  	; 20/11/2015
  1168                                  	; 24/10/2015
  1169 000007A4 2EFF15[D2390000]        	call	dword [cs:com1_irq4]
  1170 000007AB 6A04                            push 	dword 4
  1171 000007AD EB2A                    	jmp	short which_irq
  1172                                  irq5:
  1173 000007AF 6A05                            push 	dword 5
  1174 000007B1 EB26                    	jmp	short which_irq
  1175                                  irq6:
  1176 000007B3 6A06                            push 	dword 6
  1177 000007B5 EB22                    	jmp	short which_irq
  1178                                  irq7:
  1179 000007B7 6A07                            push 	dword 7
  1180 000007B9 EB1E                    	jmp	short which_irq
  1181                                  irq8:
  1182 000007BB 6A08                            push 	dword 8
  1183 000007BD EB1A                    	jmp	short which_irq
  1184                                  irq9:
  1185 000007BF 6A09                            push 	dword 9
  1186 000007C1 EB16                    	jmp	short which_irq
  1187                                  irq10:
  1188 000007C3 6A0A                            push 	dword 10
  1189 000007C5 EB12                    	jmp	short which_irq
  1190                                  irq11:
  1191 000007C7 6A0B                            push 	dword 11
  1192 000007C9 EB0E                    	jmp	short which_irq
  1193                                  irq12:
  1194 000007CB 6A0C                            push 	dword 12
  1195 000007CD EB0A                    	jmp	short which_irq
  1196                                  irq13:
  1197 000007CF 6A0D                            push 	dword 13
  1198 000007D1 EB06                    	jmp	short which_irq
  1199                                  irq14:
  1200 000007D3 6A0E                            push 	dword 14
  1201 000007D5 EB02                    	jmp	short which_irq
  1202                                  irq15:
  1203 000007D7 6A0F                            push 	dword 15
  1204                                  	;jmp	short which_irq
  1205                                  
  1206                                  	; 27/02/2022
  1207                                  	; 19/10/2015
  1208                                  	; 29/08/2014
  1209                                  	; 21/08/2014
  1210                                  which_irq:
  1211 000007D9 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1212 000007DC 53                      	push	ebx
  1213 000007DD 56                      	push	esi
  1214 000007DE 57                      	push	edi
  1215 000007DF 1E                      	push 	ds
  1216 000007E0 06                      	push 	es
  1217                                  	;
  1218 000007E1 88C3                    	mov	bl, al
  1219                                  	;
  1220 000007E3 B810000000              	mov	eax, KDATA
  1221 000007E8 8ED8                    	mov	ds, ax
  1222 000007EA 8EC0                    	mov	es, ax
  1223                                  	; 19/10/2015
  1224 000007EC FC                      	cld
  1225                                          ; 27/08/2014
  1226 000007ED 8105[E8670000]A000-             add     dword [scr_row], 0A0h
  1226 000007F5 0000               
  1227                                  	;
  1228 000007F7 B417                    	mov	ah, 17h	; blue (1) background, 
  1229                                  			; light gray (7) forecolor
  1230 000007F9 8B3D[E8670000]                  mov     edi, [scr_row]
  1231 000007FF B049                    	mov	al, 'I'
  1232 00000801 66AB                    	stosw
  1233 00000803 B052                    	mov	al, 'R'
  1234 00000805 66AB                    	stosw
  1235 00000807 B051                    	mov	al, 'Q'
  1236 00000809 66AB                    	stosw
  1237 0000080B B020                    	mov	al, ' '
  1238 0000080D 66AB                    	stosw
  1239 0000080F 88D8                    	mov	al, bl
  1240 00000811 3C0A                    	cmp	al, 10
  1241 00000813 7208                    	jb	short iix
  1242 00000815 B031                    	mov	al, '1'
  1243 00000817 66AB                    	stosw
  1244 00000819 88D8                    	mov	al, bl
  1245 0000081B 2C0A                    	sub	al, 10
  1246                                  iix:
  1247 0000081D 0430                    	add	al, '0'
  1248 0000081F 66AB                    	stosw
  1249 00000821 B020                    	mov	al, ' '
  1250 00000823 66AB                    	stosw
  1251 00000825 B021                    	mov	al, '!'
  1252 00000827 66AB                    	stosw
  1253 00000829 B020                    	mov	al, ' '
  1254 0000082B 66AB                    	stosw
  1255                                  	; 23/02/2015
  1256 0000082D 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1257                                  	;jna	iiret
  1258                                  	; 27/02/2022
  1259 00000830 7604                    	jna	short iiz
  1260                                  iiy:
  1261 00000832 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1262 00000834 E6A0                    	out	0A0h, al ; the 2nd 8259
  1263                                  iiz:
  1264 00000836 E983010000              	jmp     iiret
  1265                                  	;
  1266                                  	; 22/08/2014
  1267                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1268                                  	;out	20h, al	; 8259 PORT
  1269                                  	;
  1270                                  	;pop	es
  1271                                  	;pop	ds
  1272                                  	;pop	edi
  1273                                  	;pop	esi
  1274                                  	;pop	ebx
  1275                                  	;pop 	eax
  1276                                  	;iret
  1277                                  
  1278                                  	; 02/04/2015
  1279                                  	; 25/08/2014
  1280                                  exc0:
  1281 0000083B 6A00                            push 	dword 0
  1282 0000083D E990000000                      jmp     cpu_except
  1283                                  exc1:
  1284 00000842 6A01                            push 	dword 1
  1285 00000844 E989000000                      jmp     cpu_except
  1286                                  exc2:
  1287 00000849 6A02                            push 	dword 2
  1288 0000084B E982000000                      jmp     cpu_except
  1289                                  exc3:
  1290 00000850 6A03                            push 	dword 3
  1291 00000852 EB7E                            jmp     cpu_except
  1292                                  exc4:
  1293 00000854 6A04                            push 	dword 4
  1294 00000856 EB7A                            jmp     cpu_except
  1295                                  exc5:
  1296 00000858 6A05                            push 	dword 5
  1297 0000085A EB76                            jmp     cpu_except
  1298                                  exc6:
  1299 0000085C 6A06                            push 	dword 6
  1300 0000085E EB72                            jmp     cpu_except
  1301                                  exc7:
  1302 00000860 6A07                            push 	dword 7
  1303 00000862 EB6E                            jmp     cpu_except
  1304                                  exc8:
  1305                                  	; [esp] = Error code
  1306 00000864 6A08                            push 	dword 8
  1307 00000866 EB5C                            jmp     cpu_except_en
  1308                                  exc9:
  1309 00000868 6A09                            push 	dword 9
  1310 0000086A EB66                            jmp     cpu_except
  1311                                  exc10:
  1312                                  	; [esp] = Error code
  1313 0000086C 6A0A                            push 	dword 10
  1314 0000086E EB54                            jmp     cpu_except_en
  1315                                  exc11:
  1316                                  	; [esp] = Error code
  1317 00000870 6A0B                            push 	dword 11
  1318 00000872 EB50                            jmp     cpu_except_en
  1319                                  exc12:
  1320                                  	; [esp] = Error code
  1321 00000874 6A0C                            push 	dword 12
  1322 00000876 EB4C                            jmp     cpu_except_en
  1323                                  exc13:
  1324                                  	; [esp] = Error code
  1325 00000878 6A0D                            push 	dword 13
  1326 0000087A EB48                            jmp     cpu_except_en
  1327                                  exc14:
  1328                                  	; [esp] = Error code
  1329 0000087C 6A0E                            push 	dword 14
  1330 0000087E EB44                    	jmp	short cpu_except_en
  1331                                  exc15:
  1332 00000880 6A0F                            push 	dword 15
  1333 00000882 EB4E                            jmp     cpu_except
  1334                                  exc16:
  1335 00000884 6A10                            push 	dword 16
  1336 00000886 EB4A                            jmp     cpu_except
  1337                                  exc17:
  1338                                  	; [esp] = Error code
  1339 00000888 6A11                            push 	dword 17
  1340 0000088A EB38                    	jmp	short cpu_except_en
  1341                                  exc18:
  1342 0000088C 6A12                            push 	dword 18
  1343 0000088E EB42                    	jmp	short cpu_except
  1344                                  exc19:
  1345 00000890 6A13                            push 	dword 19
  1346 00000892 EB3E                    	jmp	short cpu_except
  1347                                  exc20:
  1348 00000894 6A14                            push 	dword 20
  1349 00000896 EB3A                    	jmp	short cpu_except
  1350                                  exc21:
  1351 00000898 6A15                            push 	dword 21
  1352 0000089A EB36                    	jmp	short cpu_except
  1353                                  exc22:
  1354 0000089C 6A16                            push 	dword 22
  1355 0000089E EB32                    	jmp	short cpu_except
  1356                                  exc23:
  1357 000008A0 6A17                            push 	dword 23
  1358 000008A2 EB2E                    	jmp	short cpu_except
  1359                                  exc24:
  1360 000008A4 6A18                            push 	dword 24
  1361 000008A6 EB2A                    	jmp	short cpu_except
  1362                                  exc25:
  1363 000008A8 6A19                            push 	dword 25
  1364 000008AA EB26                    	jmp	short cpu_except
  1365                                  exc26:
  1366 000008AC 6A1A                            push 	dword 26
  1367 000008AE EB22                    	jmp	short cpu_except
  1368                                  exc27:
  1369 000008B0 6A1B                            push 	dword 27
  1370 000008B2 EB1E                    	jmp	short cpu_except
  1371                                  exc28:
  1372 000008B4 6A1C                            push 	dword 28
  1373 000008B6 EB1A                    	jmp	short cpu_except
  1374                                  exc29:
  1375 000008B8 6A1D                            push 	dword 29
  1376 000008BA EB16                    	jmp	short cpu_except
  1377                                  exc30:
  1378 000008BC 6A1E                            push 	dword 30
  1379 000008BE EB04                    	jmp	short cpu_except_en
  1380                                  exc31:
  1381 000008C0 6A1F                            push 	dword 31
  1382 000008C2 EB0E                            jmp     short cpu_except
  1383                                  
  1384                                  	; 27/02/2022
  1385                                  	; 19/10/2015
  1386                                  	; 19/09/2015
  1387                                  	; 01/09/2015
  1388                                  	; 28/08/2015
  1389                                  	; 28/08/2014
  1390                                  cpu_except_en:
  1391 000008C4 87442404                	xchg	eax, [esp+4] ; Error code
  1392 000008C8 36A3[486D0000]          	mov	[ss:error_code], eax
  1393 000008CE 58                      	pop	eax  ; Exception number
  1394 000008CF 870424                  	xchg	eax, [esp]
  1395                                  		; eax = eax before exception
  1396                                  		; [esp] -> exception number
  1397                                  		; [esp+4] -> EIP to return
  1398                                  	; 19/10/2015
  1399                                  	; 19/09/2015
  1400                                  	; 01/09/2015
  1401                                  	; 28/08/2015
  1402                                  	; 29/08/2014
  1403                                  	; 28/08/2014
  1404                                  	; 25/08/2014
  1405                                  	; 21/08/2014
  1406                                  cpu_except:	; CPU Exceptions
  1407 000008D2 FC                      	cld
  1408 000008D3 870424                  	xchg	eax, [esp] 
  1409                                  		; eax = Exception number
  1410                                  		; [esp] = eax (before exception)	
  1411 000008D6 53                      	push	ebx
  1412 000008D7 56                      	push	esi
  1413 000008D8 57                      	push	edi
  1414 000008D9 1E                      	push 	ds
  1415 000008DA 06                      	push 	es
  1416                                  	; 28/08/2015
  1417 000008DB 66BB1000                	mov	bx, KDATA
  1418 000008DF 8EDB                    	mov	ds, bx
  1419 000008E1 8EC3                    	mov	es, bx
  1420 000008E3 0F20DB                  	mov	ebx, cr3
  1421 000008E6 53                      	push	ebx ; (*) page directory
  1422                                  	; 19/10/2015
  1423 000008E7 FC                      	cld
  1424                                  	; 25/03/2015
  1425 000008E8 8B1D[986C0000]          	mov	ebx, [k_page_dir]
  1426 000008EE 0F22DB                  	mov	cr3, ebx
  1427                                  	; 28/08/2015
  1428 000008F1 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT	
  1429 000008F4 7513                    	jne	short cpu_except_nfp
  1430 000008F6 E884270000              	call	page_fault_handler
  1431 000008FB 21C0                    	and 	eax, eax
  1432                                          ;jz	iiretp ; 01/09/2015
  1433                                  	; 27/02/2022
  1434 000008FD 7505                    	jnz	short cpu_except_pf
  1435 000008FF E9B6000000              	jmp	iiretp
  1436                                  cpu_except_pf:
  1437 00000904 B80E000000              	mov	eax, 0Eh ; 14
  1438                                  cpu_except_nfp:
  1439                                  	; 02/04/2015
  1440 00000909 BB[33060000]            	mov	ebx, hang
  1441 0000090E 875C241C                	xchg	ebx, [esp+28]
  1442                                  		; EIP (points to instruction which faults)
  1443                                  	  	; New EIP (hang)
  1444 00000912 891D[4C6D0000]          	mov	[FaultOffset], ebx
  1445 00000918 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1446 00000920 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1447                                  	;
  1448 00000928 88C4                    	mov	ah, al
  1449 0000092A 240F                    	and	al, 0Fh
  1450 0000092C 3C09                    	cmp	al, 9
  1451 0000092E 7602                    	jna	short h1ok
  1452 00000930 0407                    	add	al, 'A'-':'
  1453                                  h1ok:
  1454 00000932 D0EC                    	shr	ah, 1
  1455 00000934 D0EC                    	shr	ah, 1
  1456 00000936 D0EC                    	shr	ah, 1
  1457 00000938 D0EC                    	shr	ah, 1
  1458 0000093A 80FC09                  	cmp	ah, 9
  1459 0000093D 7603                    	jna	short h2ok
  1460 0000093F 80C407                  	add	ah, 'A'-':'
  1461                                  h2ok:	
  1462 00000942 86E0                    	xchg 	ah, al	
  1463 00000944 66053030                	add	ax, '00'
  1464 00000948 66A3[74680000]          	mov	[excnstr], ax
  1465                                  	;
  1466                                  	; 29/08/2014
  1467 0000094E A1[4C6D0000]            	mov	eax, [FaultOffset]
  1468 00000953 51                      	push	ecx
  1469 00000954 52                      	push	edx
  1470 00000955 89E3                    	mov	ebx, esp
  1471                                  	; 28/08/2015
  1472 00000957 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1473                                  			  ; to hexadecimal string
  1474                                  	;mov	ecx, 10	    ; divisor to convert	
  1475                                  			    ; binary number to decimal string
  1476                                  b2d1:
  1477 0000095C 31D2                    	xor	edx, edx
  1478 0000095E F7F1                    	div	ecx
  1479                                  	;push	dx
  1480                                  	; 27/02/2022
  1481 00000960 52                      	push	edx
  1482 00000961 39C8                    	cmp	eax, ecx
  1483 00000963 73F7                    	jnb	short b2d1
  1484 00000965 BF[7F680000]            	mov	edi, EIPstr ; EIP value
  1485                                  			    ; points to instruction which faults	
  1486                                  	; 28/08/2015
  1487 0000096A 89C2                    	mov	edx, eax
  1488                                  b2d2:
  1489                                  	;add	al, '0'
  1490 0000096C 8A82[1A170000]          	mov	al, [edx+hexchrs]
  1491 00000972 AA                      	stosb		    ; write hexadecimal digit to its place	
  1492 00000973 39E3                    	cmp	ebx, esp
  1493 00000975 7605                    	jna	short b2d3
  1494                                  	; 27/02/2022
  1495 00000977 58                      	pop	eax
  1496                                  	;pop	ax
  1497 00000978 88C2                    	mov	dl, al
  1498 0000097A EBF0                    	jmp	short b2d2
  1499                                  b2d3:
  1500 0000097C B068                    	mov 	al, 'h' ; 28/08/2015
  1501 0000097E AA                      	stosb
  1502 0000097F B020                    	mov	al, 20h	    ; space
  1503 00000981 AA                      	stosb
  1504 00000982 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1505 00000984 AA                      	stosb
  1506                                  	;
  1507 00000985 5A                      	pop	edx
  1508 00000986 59                      	pop	ecx
  1509                                  	;
  1510 00000987 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1511                                  			; white (F) forecolor
  1512 00000989 BE[64680000]            	mov	esi, exc_msg ; message offset
  1513                                  	;
  1514 0000098E EB11                    	jmp	short piemsg
  1515                                  	;
  1516                                          ;add    dword [scr_row], 0A0h
  1517                                          ;mov    edi, [scr_row]
  1518                                          ;
  1519                                  	;call 	printk
  1520                                  	;
  1521                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1522                                  	;out	20h, al	; 8259 PORT
  1523                                  	;
  1524                                  	;pop	es
  1525                                  	;pop	ds
  1526                                  	;pop	edi
  1527                                  	;pop	esi
  1528                                  	;pop 	eax
  1529                                  	;iret
  1530                                  	
  1531                                  	; 28/08/2015
  1532                                  	; 23/02/2015
  1533                                  	; 20/08/2014
  1534                                  ignore_int:
  1535 00000990 50                      	push	eax
  1536 00000991 53                      	push	ebx ; 23/02/2015
  1537 00000992 56                      	push	esi
  1538 00000993 57                      	push	edi
  1539 00000994 1E                      	push 	ds
  1540 00000995 06                      	push 	es
  1541                                  	; 28/08/2015
  1542 00000996 0F20D8                  	mov	eax, cr3
  1543 00000999 50                      	push	eax ; (*) page directory
  1544                                  	;
  1545 0000099A B467                    	mov	ah, 67h	; brown (6) background, 
  1546                                  			; light gray (7) forecolor
  1547 0000099C BE[22680000]            	mov	esi, int_msg ; message offset
  1548                                  piemsg:
  1549                                          ; 27/08/2014
  1550 000009A1 8105[E8670000]A000-             add     dword [scr_row], 0A0h
  1550 000009A9 0000               
  1551 000009AB 8B3D[E8670000]                  mov     edi, [scr_row]
  1552                                          ;
  1553 000009B1 E8B7FCFFFF              	call 	printk
  1554                                  	;
  1555                                  	; 23/02/2015
  1556 000009B6 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1557 000009B8 E6A0                    	out	0A0h, al ; the 2nd 8259
  1558                                  iiretp: ; 01/09/2015
  1559                                  	; 28/08/2015
  1560 000009BA 58                      	pop	eax ; (*) page directory
  1561 000009BB 0F22D8                  	mov	cr3, eax
  1562                                  	;
  1563                                  iiret:
  1564                                  	; 22/08/2014
  1565 000009BE B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1566 000009C0 E620                    	out	20h, al	; 8259 PORT
  1567                                  	;
  1568 000009C2 07                      	pop	es
  1569 000009C3 1F                      	pop	ds
  1570 000009C4 5F                      	pop	edi
  1571 000009C5 5E                      	pop	esi
  1572 000009C6 5B                      	pop	ebx ; 29/08/2014
  1573 000009C7 58                      	pop 	eax
  1574 000009C8 CF                      	iretd
  1575                                  
  1576                                  	; 23/02/2022
  1577                                  	; 26/02/2015
  1578                                  	; 07/09/2014
  1579                                  	; 25/08/2014
  1580                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1581                                  	; 22/08/2014
  1582 000009C9 50                      	push	eax
  1583 000009CA 53                      	push	ebx ; 29/08/2014
  1584 000009CB 56                      	push	esi
  1585 000009CC 57                      	push	edi
  1586 000009CD 1E                      	push 	ds
  1587 000009CE 06                      	push 	es
  1588                                  	;
  1589 000009CF B810000000              	mov	eax, KDATA
  1590 000009D4 8ED8                    	mov	ds, ax
  1591 000009D6 8EC0                    	mov	es, ax
  1592                                  	;
  1593                                  	; 25/08/2014
  1594                                  	;call	rtc_p
  1595                                  	; 23/02/2022
  1596 000009D8 FF15[2C070000]          	call	[x_rtci]
  1597                                  	;
  1598                                  	; 22/02/2015 - dsectpm.s
  1599                                  	; [ source: http://wiki.osdev.org/RTC ]
  1600                                  	; read status register C to complete procedure
  1601                                  	;(it is needed to get a next IRQ 8) 
  1602 000009DE B00C                    	mov	al, 0Ch ; 
  1603 000009E0 E670                    	out	70h, al ; select register C
  1604 000009E2 90                      	nop
  1605 000009E3 E471                    	in	al, 71h ; just throw away contents
  1606                                  	; 22/02/2015
  1607 000009E5 B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1608 000009E7 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1609                                  	;
  1610 000009E9 EBD3                    	jmp	short iiret	
  1611                                  
  1612                                  	; 22/08/2014
  1613                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1614                                  	; (INT 1Ah)
  1615                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1616                                  time_of_day:
  1617 000009EB E868010000              	call	UPD_IPR			; WAIT TILL UPDATE NOT IN PROGRESS
  1618 000009F0 726F                            jc      short rtc_retn 
  1619 000009F2 B000                    	mov	al, CMOS_SECONDS
  1620 000009F4 E847010000              	call	CMOS_READ
  1621 000009F9 A2[0C6D0000]            	mov	[time_seconds], al 
  1622 000009FE B002                    	mov	al, CMOS_MINUTES
  1623 00000A00 E83B010000              	call	CMOS_READ
  1624 00000A05 A2[0D6D0000]            	mov	[time_minutes], al 
  1625 00000A0A B004                    	mov	al, CMOS_HOURS
  1626 00000A0C E82F010000              	call	CMOS_READ
  1627 00000A11 A2[0E6D0000]                    mov     [time_hours], al
  1628 00000A16 B006                    	mov	al, CMOS_DAY_WEEK 
  1629 00000A18 E823010000              	call	CMOS_READ
  1630 00000A1D A2[0F6D0000]            	mov	[date_wday], al
  1631 00000A22 B007                     	mov	al, CMOS_DAY_MONTH
  1632 00000A24 E817010000              	call	CMOS_READ
  1633 00000A29 A2[106D0000]            	mov	[date_day], al
  1634 00000A2E B008                    	mov	al, CMOS_MONTH
  1635 00000A30 E80B010000              	call	CMOS_READ
  1636 00000A35 A2[116D0000]            	mov	[date_month], al
  1637 00000A3A B009                    	mov	al, CMOS_YEAR
  1638 00000A3C E8FF000000              	call	CMOS_READ
  1639 00000A41 A2[126D0000]            	mov	[date_year], al
  1640 00000A46 B032                    	mov	al, CMOS_CENTURY
  1641 00000A48 E8F3000000              	call	CMOS_READ
  1642 00000A4D A2[136D0000]            	mov	[date_century], al
  1643                                  	;
  1644 00000A52 B000                    	mov	al, CMOS_SECONDS
  1645 00000A54 E8E7000000              	call 	CMOS_READ
  1646 00000A59 3A05[0C6D0000]          	cmp	al, [time_seconds]
  1647 00000A5F 758A                    	jne	short time_of_day
  1648                                  
  1649                                  rtc_retn:
  1650 00000A61 C3                      	retn
  1651                                  
  1652                                  rtci_default:
  1653                                  	; 23/02/2022 (Temporary!)
  1654                                  	; (default real time clock handler in multitasking mode)
  1655                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1656 00000A62 FF05[546D0000]          	inc	dword [rtc_ticks] ; real time clock counter
  1657                                  			; (not used in anywhere of kernel for now!)
  1658 00000A68 C3                      	retn
  1659                                  
  1660                                  rtc_p:	
  1661                                  	; 27/02/2022
  1662                                  	; 12/02/2022
  1663                                  	; 07/09/2014
  1664                                  	; 29/08/2014
  1665                                  	; 27/08/2014
  1666                                  	; 25/08/2014
  1667                                   	; Print Real Time Clock content
  1668                                  	;
  1669                                  	;
  1670 00000A69 E87DFFFFFF              	call	time_of_day
  1671 00000A6E 72F1                    	jc	short rtc_retn
  1672                                  	;
  1673 00000A70 3A05[D6680000]          	cmp	al, [ptime_seconds]
  1674 00000A76 74E9                            je      short rtc_retn ; 29/08/2014
  1675                                  	;
  1676 00000A78 A2[D6680000]            	mov	[ptime_seconds], al
  1677                                  	;
  1678 00000A7D A0[136D0000]            	mov	al, [date_century]
  1679 00000A82 E8EC000000              	call	bcd_to_ascii
  1680 00000A87 66A3[A3680000]          	mov	[datestr+6], ax
  1681 00000A8D A0[126D0000]            	mov	al, [date_year]
  1682 00000A92 E8DC000000              	call	bcd_to_ascii
  1683 00000A97 66A3[A5680000]          	mov	[datestr+8], ax
  1684 00000A9D A0[116D0000]            	mov	al, [date_month]
  1685 00000AA2 E8CC000000              	call	bcd_to_ascii
  1686 00000AA7 66A3[A0680000]          	mov	[datestr+3], ax
  1687 00000AAD A0[106D0000]            	mov	al, [date_day]
  1688 00000AB2 E8BC000000              	call	bcd_to_ascii
  1689 00000AB7 66A3[9D680000]          	mov	[datestr], ax
  1690                                  	;
  1691 00000ABD 0FB61D[0F6D0000]        	movzx	ebx, byte [date_wday]
  1692 00000AC4 C0E302                  	shl 	bl, 2
  1693 00000AC7 81C3[B6680000]          	add	ebx, daytmp
  1694 00000ACD 8B03                    	mov	eax, [ebx]
  1695 00000ACF A3[A8680000]            	mov	[daystr], eax
  1696                                  	;
  1697 00000AD4 A0[0E6D0000]            	mov	al, [time_hours]
  1698 00000AD9 E895000000              	call	bcd_to_ascii
  1699 00000ADE 66A3[AC680000]          	mov	[timestr], ax
  1700 00000AE4 A0[0D6D0000]            	mov	al, [time_minutes]
  1701 00000AE9 E885000000              	call	bcd_to_ascii
  1702 00000AEE 66A3[AF680000]          	mov	[timestr+3], ax
  1703 00000AF4 A0[0C6D0000]            	mov	al, [time_seconds]
  1704 00000AF9 E875000000              	call	bcd_to_ascii
  1705 00000AFE 66A3[B2680000]          	mov	[timestr+6], ax
  1706                                  	;		
  1707 00000B04 BE[8B680000]            	mov	esi, rtc_msg ; message offset
  1708                                  	; 23/02/2015
  1709 00000B09 52                      	push	edx
  1710 00000B0A 51                      	push	ecx
  1711                                  	; 07/09/2014
  1712                                  	;mov	bx, 2	; Video page 2
  1713                                  	; 27/02/2022
  1714 00000B0B 29DB                    	sub	ebx, ebx
  1715 00000B0D B307                    	mov	bl, 7	; Video page 7
  1716                                  prtmsg:
  1717 00000B0F AC                      	lodsb
  1718 00000B10 08C0                    	or	al, al
  1719 00000B12 740D                    	jz	short prtmsg_ok
  1720 00000B14 56                      	push	esi
  1721                                  	; 27/02/2022
  1722 00000B15 53                      	push	ebx
  1723                                  	;push	bx
  1724 00000B16 B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1725                                  			; white (F) forecolor
  1726 00000B18 E8BD080000              	call 	write_tty
  1727                                  	;pop	bx
  1728                                  	; 27/02/2022
  1729 00000B1D 5B                      	pop	ebx
  1730 00000B1E 5E                      	pop	esi
  1731 00000B1F EBEE                    	jmp	short prtmsg
  1732                                  	;
  1733                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1734                                  	;call	printk
  1735                                  prtmsg_ok:
  1736                                  	; 07/09/2014
  1737                                  	;xor	dx, dx		; column 0, row 0
  1738                                  	; 27/02/2022
  1739 00000B21 31D2                    	xor	edx, edx
  1740 00000B23 E8BC090000              	call	set_cpos	; set cursor position to 0,0 
  1741                                  	; 23/02/2015
  1742 00000B28 59                      	pop	ecx
  1743 00000B29 5A                      	pop	edx
  1744 00000B2A C3                      	retn
  1745                                  
  1746                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1747                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1748                                  default_irq7:
  1749                                  	; 27/02/2022
  1750                                  	;push	ax
  1751 00000B2B 50                      	push	eax
  1752 00000B2C B00B                    	mov	al, 0Bh  ; In-Service register
  1753 00000B2E E620                    	out	20h, al
  1754 00000B30 EB00                            jmp short $+2
  1755 00000B32 EB00                    	jmp short $+2
  1756 00000B34 E420                    	in	al, 20h
  1757 00000B36 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1758 00000B38 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1759 00000B3A B020                            mov     al, 20h ; EOI
  1760 00000B3C E620                    	out	20h, al 
  1761                                  irq7_iret:
  1762                                  	;pop	ax
  1763                                  	; 27/02/2022
  1764 00000B3E 58                      	pop	eax
  1765 00000B3F CF                      	iretd
  1766                                  	
  1767                                  	; 22/08/2014
  1768                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1769                                  CMOS_READ:
  1770 00000B40 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1771 00000B41 D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1772 00000B43 F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1773 00000B44 D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1774 00000B46 FA                      	cli		; DISABLE INTERRUPTS
  1775 00000B47 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1776 00000B49 90                      	nop		; I/O DELAY
  1777 00000B4A E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1778 00000B4C 6650                    	push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1779                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1780                                  		     ; ----- 10/06/85 (test4.asm)
  1781 00000B4E B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1782                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1783 00000B50 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1784 00000B52 E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1785 00000B54 6658                    	pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1786 00000B56 9D                      	popf	
  1787 00000B57 C3                      	retn		; RETURN WITH FLAGS RESTORED
  1788                                  
  1789                                  	; 22/08/2014
  1790                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1791                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1792 00000B58 51                      	push	ecx
  1793 00000B59 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1794                                  		; mov cx, 800	
  1795                                  UPD_10:
  1796 00000B5E B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1797 00000B60 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1798 00000B61 E8DAFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1799 00000B66 A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1800 00000B68 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1801 00000B6A FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1802 00000B6B E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1803 00000B6D 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1804                                  		; xor ax, ax
  1805 00000B6F F9                      	stc				; SET CARRY FOR ERROR
  1806                                  UPD_90:
  1807 00000B70 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1808 00000B71 FA                      	cli				; INTERRUPTS OFF DURING SET
  1809 00000B72 C3                      	retn				; RETURN WITH CY FLAG SET
  1810                                  
  1811                                  bcd_to_ascii:
  1812                                  	; 25/08/2014
  1813                                  	; INPUT ->
  1814                                  	;	al = Packed BCD number
  1815                                  	; OUTPUT ->
  1816                                  	;	ax  = ASCII word/number
  1817                                  	;
  1818                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1819                                  	;
  1820 00000B73 D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1821                                  					; AH = AL / 10h
  1822                                  					; AL = AL MOD 10h
  1823 00000B75 660D3030                	or ax,'00'                      ; Make it ASCII based
  1824                                  
  1825 00000B79 86E0                            xchg ah, al 
  1826                                  	
  1827 00000B7B C3                      	retn	
  1828                                  	
  1829                                  %include 'keyboard.inc' ; 07/03/2015
  1830                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - KEYBOARD.INC
  1831                              <1> ; Last Modification: 13/06/2022
  1832                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1833                              <1> ;
  1834                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1835                              <1> 
  1836                              <1> ; 13/06/2022 (Retro UNIX 386 v1, Kernel v0.2.0.20)
  1837                              <1> ; 23/02/2022 
  1838                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1839                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1840                              <1> ; 30/06/2015
  1841                              <1> ; 11/03/2015
  1842                              <1> ; 28/02/2015
  1843                              <1> ; 25/02/2015
  1844                              <1> ; 20/02/2015
  1845                              <1> ; 18/02/2015
  1846                              <1> ; 03/12/2014
  1847                              <1> ; 07/09/2014
  1848                              <1> ; KEYBOARD INTERRUPT HANDLER
  1849                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1850                              <1> 
  1851                              <1> ;getch:
  1852                              <1> ;	; 18/02/2015
  1853                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1854                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1855                              <1> ;	; routine, later... (multi tasking ability)
  1856                              <1> ;	; 28/02/2015
  1857                              <1> ;	sti	; enable interrupts
  1858                              <1> ;	;
  1859                              <1> ;	;push	esi
  1860                              <1> ;	;push	ebx
  1861                              <1> ;	;xor	ebx, ebx
  1862                              <1> ;	;mov	bl, [ptty]  ; active_page
  1863                              <1> ;	;mov	esi, ebx
  1864                              <1> ;	;shl 	si, 1
  1865                              <1> ;	;add	esi, ttychr
  1866                              <1> ;getch_1:
  1867                              <1> ;	;mov	ax, [esi]
  1868                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1869                              <1> ;	and	ax, ax
  1870                              <1> ;	jz	short getch_2
  1871                              <1> ;	mov	word [ttychr], 0
  1872                              <1> ;	;mov	word [esi], 0
  1873                              <1> ;	;pop	ebx
  1874                              <1> ;	;pop	esi
  1875                              <1> ;	retn
  1876                              <1> ;getch_2:
  1877                              <1> ;	hlt	; not proper for multi tasking!
  1878                              <1> ;		; (temporary halt for now)
  1879                              <1> ;		; 'sleep' on tty 
  1880                              <1> ;		; will (must) be located here		
  1881                              <1> ;	nop
  1882                              <1> ;	jmp	short getch_1
  1883                              <1> 
  1884                              <1> keyb_int:
  1885                              <1> 	; 23/02/2022
  1886                              <1> 	; 30/06/2015
  1887                              <1> 	; 25/02/2015
  1888                              <1> 	; 20/02/2015
  1889                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1890                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1891                              <1> 	; 30/06/2014
  1892                              <1> 	; 10/05/2013	
  1893                              <1>       	; Retro Unix 8086 v1 feature only!
  1894                              <1> 	; 03/03/2014
  1895                              <1> 	
  1896 00000B7C 1E                  <1> 	push	ds
  1897 00000B7D 53                  <1> 	push	ebx
  1898 00000B7E 50                  <1> 	push	eax
  1899                              <1> 	;
  1900                              <1> 	; 23/02/2022
  1901 00000B7F 9C                  <1> 	pushfd
  1902 00000B80 0E                  <1> 	push	cs
  1903                              <1> 	;mov	ax, KDATA
  1904 00000B81 31C0                <1> 	xor	eax, eax
  1905 00000B83 B010                <1> 	mov	al, KDATA
  1906 00000B85 8ED8                <1> 	mov	ds, ax
  1907                              <1> 	;
  1908                              <1> 	;pushfd
  1909                              <1> 	;push	cs
  1910 00000B87 E810020000          <1> 	call	kb_int   ; int_09h
  1911                              <1> 	;
  1912 00000B8C B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1913                              <1> 	;call	getc
  1914 00000B8E E854000000          <1> 	call	int_16h  ; 30/06/2015
  1915 00000B93 744E                <1> 	jz	short keyb_int4
  1916                              <1> 	;
  1917 00000B95 B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1918                              <1> 	;call	getc
  1919 00000B97 E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1920                              <1> 	;
  1921                              <1> 	; 20/02/2015
  1922 00000B9C 0FB61D[C66C0000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1923                              <1> 	;
  1924 00000BA3 20C0                <1> 	and 	al, al
  1925 00000BA5 751D                <1> 	jnz	short keyb_int1
  1926                              <1> 	;
  1927 00000BA7 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1928 00000BAA 7218                <1> 	jb	short keyb_int1
  1929 00000BAC 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1930 00000BAF 7713                <1> 	ja	short keyb_int1
  1931                              <1> 	;
  1932 00000BB1 88D8                <1> 	mov	al, bl
  1933 00000BB3 0468                <1> 	add	al, 68h
  1934 00000BB5 38E0                <1> 	cmp	al, ah
  1935 00000BB7 7409                <1> 	je	short keyb_int0
  1936 00000BB9 88E0                <1> 	mov	al, ah
  1937 00000BBB 2C68                <1> 	sub	al, 68h
  1938 00000BBD E8370A0000          <1> 	call	tty_sw
  1939                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1940                              <1> keyb_int0: ; 30/06/2015
  1941                              <1> 	;xor	ax, ax
  1942                              <1> 	; 23/02/2022
  1943 00000BC2 31C0                <1> 	xor	eax, eax
  1944                              <1> keyb_int1:
  1945 00000BC4 D0E3                <1> 	shl	bl, 1
  1946 00000BC6 81C3[C86C0000]      <1> 	add	ebx, ttychr
  1947                              <1> 	;
  1948                              <1> 	;23/02/2022
  1949 00000BCC 09C0                <1> 	or	eax, eax
  1950                              <1> 	;or	ax, ax
  1951 00000BCE 7406                <1> 	jz	short keyb_int2
  1952                              <1> 	;
  1953 00000BD0 66833B00            <1> 	cmp 	word [ebx], 0
  1954 00000BD4 7703                <1>         ja      short keyb_int3 
  1955                              <1> keyb_int2:
  1956 00000BD6 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1957                              <1> 			   ; and scan code of the character
  1958                              <1> 			   ; for current tty (or last tty
  1959                              <1> 			   ; just before tty switch).
  1960                              <1> keyb_int3:
  1961 00000BD9 A0[C66C0000]        <1>         mov     al, [ptty]
  1962 00000BDE E8F7430000          <1> 	call	wakeup
  1963                              <1> 	;
  1964                              <1> keyb_int4:
  1965 00000BE3 58                  <1> 	pop	eax
  1966 00000BE4 5B                  <1> 	pop	ebx
  1967 00000BE5 1F                  <1> 	pop	ds
  1968 00000BE6 CF                  <1> 	iret
  1969                              <1> 
  1970                              <1> ; 18/02/2015
  1971                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  1972                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  1973                              <1> ; scancode and ascii code of the character 
  1974                              <1> ; in the tty input (ttychr) buffer. 
  1975                              <1> ; Test procedures must call 'getch' for tty input
  1976                              <1> ; otherwise, 'getc' will not be able to return to the caller
  1977                              <1> ; due to infinite (key press) waiting loop.
  1978                              <1> ; 
  1979                              <1> ; 03/12/2014
  1980                              <1> ; 26/08/2014
  1981                              <1> ; KEYBOARD I/O
  1982                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  1983                              <1> 
  1984                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  1985                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  1986                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  1987                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  1988                              <1> 
  1989                              <1> int_16h: ; 30/06/2015
  1990                              <1> ;getc:
  1991 00000BE7 9C                  <1> 	pushfd	; 28/08/2014
  1992 00000BE8 0E                  <1> 	push 	cs
  1993 00000BE9 E826000000          <1> 	call 	getc_int
  1994 00000BEE C3                  <1> 	retn
  1995                              <1> 
  1996                              <1> ; 24/12/2021
  1997                              <1> 
  1998                              <1> 	;-----	SHIFT STATUS
  1999                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2000 00000BEF 8A25[C4660000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2001 00000BF5 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2002                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2003                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2004 00000BF8 C0E405              <1>         shl	ah, 5
  2005 00000BFB A0[C4660000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2006 00000C00 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2007 00000C02 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2008 00000C04 A0[C6660000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2009 00000C09 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2010 00000C0B 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2011                              <1> _K3:
  2012 00000C0D A0[C3660000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2013 00000C12 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2014                              <1> 
  2015                              <1> getc_int:
  2016                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2017                              <1> 	; 28/02/2015
  2018                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2019                              <1> 	;	      instead of pc-at bios - 1985-)
  2020                              <1> 	; 28/08/2014 (_k1d)
  2021                              <1> 	; 30/06/2014
  2022                              <1> 	; 03/03/2014
  2023                              <1> 	; 28/02/2014
  2024                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2025                              <1> 	; rombios source code (21/04/1986)
  2026                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2027                              <1> 	;
  2028                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2029                              <1> 	;
  2030                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2031                              <1> 	; KEYBOARD I/O								      :
  2032                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2033                              <1> 	; INPUT									      :
  2034                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2035                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2036                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2037                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2038                              <1> 	;-----------------------------------------------------------------------------:
  2039                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2040                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2041                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2042                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2043                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2044                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2045                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2046                              <1> 	;-----------------------------------------------------------------------------:	
  2047                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2048                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2049                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2050                              <1> 	;-----------------------------------------------------------------------------:	
  2051                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2052                              <1> 	;	      (AL) = 05H                                                      :
  2053                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2054                              <1> 	;		       							      :
  2055                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2056                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2057                              <1> 	;                     --------------------------------------------            :
  2058                              <1> 	;			00H        30.0        10H        7.5                 :
  2059                              <1> 	;			01H        26.7        11H        6.7                 :
  2060                              <1> 	;			02H        24.0        12H        6.0                 :
  2061                              <1> 	;			03H        21.8        13H        5.5                 :
  2062                              <1> 	;			04H        20.0        14H        5.0                 :
  2063                              <1> 	;			05H        18.5        15H        4.6                 :
  2064                              <1> 	;			06H        17.1        16H        4.3                 :
  2065                              <1> 	;			07H        16.0        17H        4.0                 :
  2066                              <1> 	;			08H        15.0        18H        3.7                 :
  2067                              <1> 	;			09H        13.3        19H        3.3                 :
  2068                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2069                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2070                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2071                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2072                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2073                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2074                              <1> 	;									      :
  2075                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2076                              <1> 	;		       							      :
  2077                              <1> 	;                     REGISTER     DELAY                                      :
  2078                              <1> 	;                      VALUE       VALUE                                      :
  2079                              <1> 	;                     ------------------                                      :
  2080                              <1> 	;			00H        250 ms                                     :
  2081                              <1> 	;			01H        500 ms                                     :
  2082                              <1> 	;			02H        750 ms                                     :
  2083                              <1> 	;			03H       1000 ms                                     :
  2084                              <1> 	;-----------------------------------------------------------------------------:
  2085                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2086                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2087                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2088                              <1> 	;		           (CH) = SCAN CODE                                   :
  2089                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2090                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2091                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2092                              <1> 	;-----------------------------------------------------------------------------:		
  2093                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2094                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2095                              <1> 	;-----------------------------------------------------------------------------:
  2096                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2097                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2098                              <1> 	;-----------------------------------------------------------------------------:	
  2099                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2100                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2101                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2102                              <1> 	; OUTPUT					                              :
  2103                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2104                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2105                              <1> 	;------------------------------------------------------------------------------
  2106                              <1> 	
  2107 00000C14 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2108 00000C15 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2109 00000C16 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2110                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2111 00000C17 66BB1000            <1>         mov     bx, KDATA 
  2112 00000C1B 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2113 00000C1D 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2114 00000C1F 742D                <1> 	jz	short _K1		; ASCII_READ
  2115 00000C21 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2116 00000C23 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2117 00000C25 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2118 00000C27 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2119 00000C29 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2120 00000C2B 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2121 00000C2D 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2122 00000C30 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2123                              <1> _KIO1:	
  2124 00000C32 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2125 00000C35 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2126 00000C37 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2127 00000C39 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2128 00000C3B FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2129 00000C3D 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2130                              <1> _KIO_EXIT:
  2131                              <1> 	;pop	ecx			; RECOVER REGISTER
  2132 00000C3F 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2133 00000C40 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2134 00000C41 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2135                              <1> 
  2136                              <1> 	;-----	ASCII CHARACTER
  2137                              <1> _K1E:	
  2138 00000C42 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2139 00000C47 E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2140 00000C4C EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2141                              <1> _K1:	
  2142 00000C4E E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2143 00000C53 E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2144 00000C58 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2145                              <1> _K1A:
  2146 00000C5A EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2147                              <1> 
  2148                              <1> 	;-----	ASCII STATUS
  2149                              <1> _K2E:	
  2150 00000C5C E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2151 00000C61 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2152 00000C63 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2153 00000C64 E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2154 00000C69 EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2155                              <1> _K2:	
  2156 00000C6B E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2157 00000C70 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2158 00000C72 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2159 00000C73 E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2160 00000C78 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2161 00000C7A 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2162 00000C7B E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2163 00000C80 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2164                              <1> _K2A:
  2165 00000C82 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2166                              <1> _K2B:
  2167                              <1> 	;pop	ecx			; RECOVER REGISTER
  2168 00000C83 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2169 00000C84 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2170 00000C85 CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2171                              <1> 
  2172                              <1> ; 24/12/2021
  2173                              <1> ;	;-----	SHIFT STATUS
  2174                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2175                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2176                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2177                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2178                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2179                              <1> ;       shl	ah, 5
  2180                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2181                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2182                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2183                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2184                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2185                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2186                              <1> ;_K3:
  2187                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2188                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2189                              <1> 
  2190                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2191                              <1> _K300:
  2192 00000C88 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2193 00000C8A 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2194 00000C8C F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2195 00000C8F 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2196 00000C91 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2197 00000C94 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2198 00000C96 B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2199 00000C98 E87C060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2200                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2201                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2202 00000C9D C0E705              <1> 	shl	bh, 5
  2203 00000CA0 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2204 00000CA2 08F8                <1> 	or	al, bh			; AND DELAY
  2205 00000CA4 E870060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2206 00000CA9 EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2207                              <1> 
  2208                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2209                              <1> _K500:
  2210 00000CAB 56                  <1> 	push	esi			; SAVE SI (esi)
  2211 00000CAC FA                  <1> 	cli				; 
  2212 00000CAD 8B1D[D4660000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2213 00000CB3 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2214 00000CB5 E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2215 00000CBA 3B1D[D0660000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2216 00000CC0 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2217 00000CC2 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2218 00000CC5 891D[D4660000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2219 00000CCB 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2220 00000CCD EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2221                              <1> _K502:
  2222 00000CCF B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2223                              <1> _K504:
  2224 00000CD1 FB                  <1> 	sti				
  2225 00000CD2 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2226 00000CD3 E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2227                              <1> 
  2228                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2229                              <1> _K1S:
  2230 00000CD8 FA                  <1> 	cli	; 03/12/2014
  2231 00000CD9 8B1D[D0660000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2232 00000CDF 3B1D[D4660000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2233                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2234 00000CE5 750F                <1> 	jne	short _k1x ; 03/12/2014
  2235                              <1> 	;
  2236                              <1> 	; 03/12/2014
  2237                              <1> 	; 28/08/2014
  2238                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2239                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2240                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2241                              <1> _K1T:                                   ; ASCII READ
  2242 00000CE7 FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2243 00000CE8 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2244                              <1> _K1U:	
  2245 00000CE9 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2246 00000CEA 8B1D[D0660000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2247 00000CF0 3B1D[D4660000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2248                              <1> _k1x:
  2249 00000CF6 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2250 00000CF7 9C                  <1> 	pushf				; SAVE FLAGS
  2251 00000CF8 E8D0060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2252 00000CFD 8A1D[C5660000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2253 00000D03 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2254 00000D05 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2255 00000D08 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2256 00000D0A E86A060000          <1> 	call	SND_LED1
  2257 00000D0F FA                  <1> 	cli				; DISABLE INTERRUPTS
  2258                              <1> _K1V:
  2259 00000D10 9D                  <1> 	popf				; RESTORE FLAGS
  2260 00000D11 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2261 00000D12 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2262                              <1> 	;
  2263 00000D14 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2264 00000D17 E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2265 00000D1C 891D[D0660000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2266 00000D22 C3                  <1> 	retn				; RETURN
  2267                              <1> 
  2268                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2269                              <1> _K2S:
  2270 00000D23 FA                  <1> 	cli				; INTERRUPTS OFF
  2271 00000D24 8B1D[D0660000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2272 00000D2A 3B1D[D4660000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2273 00000D30 668B03              <1> 	mov	ax, [ebx]
  2274 00000D33 9C                  <1> 	pushf				; SAVE FLAGS
  2275                              <1> 	;push	ax			; SAVE CODE
  2276                              <1> 	; 24/12/2021
  2277 00000D34 50                  <1> 	push	eax
  2278 00000D35 E893060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2279 00000D3A 8A1D[C5660000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2280 00000D40 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2281 00000D42 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2282 00000D45 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2283 00000D47 E816060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2284                              <1> _K2T:
  2285                              <1> 	;pop	ax			; RESTORE CODE
  2286                              <1> 	; 24/12/2021
  2287 00000D4C 58                  <1> 	pop	eax
  2288 00000D4D 9D                  <1> 	popf				; RESTORE FLAGS
  2289 00000D4E FB                  <1> 	sti				; INTERRUPTS BACK ON
  2290 00000D4F C3                  <1> 	retn				; RETURN
  2291                              <1> 
  2292                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2293                              <1> _KIO_E_XLAT:
  2294 00000D50 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2295 00000D52 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2296 00000D54 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2297 00000D56 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2298 00000D58 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2299                              <1> _KIO_E_RET:				
  2300 00000D5A C3                  <1> 	retn				; GO BACK
  2301                              <1> 
  2302                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2303                              <1> _KIO_S_XLAT:
  2304 00000D5B 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2305 00000D5E 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2306 00000D60 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2307 00000D62 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2308 00000D64 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2309 00000D66 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2310 00000D68 B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2311                              <1> _kio_ret: ; 03/12/2014
  2312 00000D6A F8                  <1> 	clc
  2313 00000D6B C3                  <1> 	retn
  2314                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2315                              <1> _KIO_S1:				
  2316 00000D6C B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2317                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2318 00000D6E C3                  <1> 	retn
  2319                              <1> _KIO_S2:		
  2320 00000D6F 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2321 00000D72 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2322 00000D74 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2323 00000D76 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2324 00000D78 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2325 00000D7A 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2326 00000D7C EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2327                              <1> _KIO_S3:
  2328 00000D7E 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2329                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2330 00000D80 75E8                <1> 	jne	short _kio_ret
  2331 00000D82 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2332 00000D84 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2333 00000D86 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2334                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2335                              <1> _KIO_USE:
  2336                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2337 00000D88 C3                  <1> 	retn				; RETURN	
  2338                              <1> _KIO_DIS:
  2339 00000D89 F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2340 00000D8A C3                  <1> 	retn				; RETURN
  2341                              <1> 
  2342                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2343                              <1> _K4:    
  2344 00000D8B 43                  <1> 	inc     ebx
  2345 00000D8C 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2346 00000D8D 3B1D[CC660000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2347                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2348 00000D93 7206                <1> 	jb	short _K5
  2349 00000D95 8B1D[C8660000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2350                              <1> _K5:
  2351 00000D9B C3                  <1> 	retn
  2352                              <1> 
  2353                              <1> ; 20/02/2015
  2354                              <1> ; 05/12/2014
  2355                              <1> ; 26/08/2014
  2356                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2357                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2358                              <1> ;
  2359                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2360                              <1> ; rombios source code (06/10/1985)
  2361                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2362                              <1> 
  2363                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2364                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2365                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2366                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2367                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2368                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2369                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2370                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2371                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2372                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2373                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2374                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2375                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2376                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2377                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2378                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2379                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2380                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2381                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2382                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2383                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2384                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2385                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2386                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2387                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2388                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2389                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2390                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2391                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2392                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2393                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2394                              <1> F11_M		equ	87		; F11 KEY MAKE
  2395                              <1> F12_M		equ	88		; F12 KEY MAKE
  2396                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2397                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2398                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2399                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2400                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2401                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2402                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2403                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2404                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2405                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2406                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2407                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2408                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2409                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2410                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2411                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2412                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2413                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2414                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2415                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2416                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2417                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2418                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2419                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2420                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2421                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2422                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2423                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2424                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2425                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2426                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2427                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2428                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2429                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2430                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2431                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2432                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2433                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2434                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2435                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2436                              <1> ;
  2437                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2438                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2439                              <1> INTA00		equ	020h		; 8259 PORT
  2440                              <1> 
  2441                              <1> 
  2442                              <1> kb_int:
  2443                              <1> 
  2444                              <1> ; 13/06/2022
  2445                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2446                              <1> ; 17/10/2015 ('ctrlbrk') 
  2447                              <1> ; 05/12/2014
  2448                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2449                              <1> 	;	      instead of pc-at bios - 1985-)
  2450                              <1> ; 26/08/2014
  2451                              <1> ;
  2452                              <1> ; 03/06/86  KEYBOARD BIOS
  2453                              <1> ;
  2454                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2455                              <1> ;										;
  2456                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2457                              <1> ;										;
  2458                              <1> ;--------------------------------------------------------------------------------
  2459                              <1> 
  2460                              <1> KB_INT_1:
  2461 00000D9C FB                  <1> 	sti				; ENABLE INTERRUPTS
  2462                              <1> 	;push	ebp
  2463 00000D9D 50                  <1> 	push	eax
  2464 00000D9E 53                  <1> 	push	ebx
  2465 00000D9F 51                  <1> 	push	ecx
  2466 00000DA0 52                  <1> 	push	edx
  2467 00000DA1 56                  <1> 	push	esi
  2468 00000DA2 57                  <1> 	push	edi
  2469 00000DA3 1E                  <1> 	push	ds
  2470 00000DA4 06                  <1> 	push	es
  2471 00000DA5 FC                  <1> 	cld				; FORWARD DIRECTION
  2472 00000DA6 66B81000            <1> 	mov	ax, KDATA
  2473 00000DAA 8ED8                <1> 	mov	ds, ax
  2474 00000DAC 8EC0                <1> 	mov	es, ax
  2475                              <1> 	;
  2476                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2477 00000DAE B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2478 00000DB0 E852050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2479 00000DB5 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2480 00000DB6 B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2481                              <1> KB_INT_01:
  2482 00000DBB E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2483 00000DBD A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2484 00000DBF E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2485                              <1> 	;
  2486                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2487 00000DC1 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2488                              <1> 	;
  2489                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2490                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2491                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2492                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2493                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2494                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2495                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2496                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2497                              <1> 	;
  2498                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2499                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2500 00000DC3 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2501 00000DC4 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2502 00000DC6 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2503                              <1> 	;
  2504                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2505 00000DC8 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2506 00000DCA 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2507                              <1> 	;
  2508                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2509 00000DCC FA                  <1> 	cli				; DISABLE INTERRUPTS
  2510 00000DCD 800D[C5660000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2511 00000DD4 E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2512                              <1> 	;
  2513                              <1> 	;-----	RESEND THE LAST BYTE
  2514                              <1> KB_INT_4:
  2515 00000DD9 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2516 00000DDA 800D[C5660000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2517 00000DE1 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2518                              <1> 	;
  2519                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2520                              <1> KB_INT_2:
  2521                              <1> 	;push 	ax			; SAVE DATA IN
  2522                              <1> 	; 24/12/2021
  2523 00000DE6 50                  <1> 	push	eax
  2524 00000DE7 E8E1050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2525 00000DEC 8A1D[C5660000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2526 00000DF2 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2527 00000DF4 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2528 00000DF7 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2529 00000DF9 E864050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2530                              <1> UP0:
  2531                              <1> 	;pop	ax			; RESTORE DATA IN
  2532                              <1> 	; 24/12/2021
  2533 00000DFE 58                  <1> 	pop	eax
  2534                              <1> ;------------------------------------------------------------------------
  2535                              <1> ;	START OF KEY PROCESSING						;
  2536                              <1> ;------------------------------------------------------------------------
  2537 00000DFF 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2538                              <1> 	;
  2539                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2540 00000E01 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2541                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2542                              <1> 	; 24/12/2021
  2543 00000E03 7505                <1> 	jne	short K16
  2544 00000E05 E9E9040000          <1> 	jmp	K62
  2545                              <1> K16:	
  2546 00000E0A 8A3D[C6660000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2547                              <1> 	;
  2548                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2549 00000E10 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2550 00000E13 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2551 00000E15 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2552 00000E17 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2553 00000E19 7507                <1> 	jne	short RST_RD_ID
  2554 00000E1B 800D[C6660000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2555                              <1> RST_RD_ID:
  2556 00000E22 8025[C6660000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2557 00000E29 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2558                              <1> 	; 24/12/2021
  2559                              <1> 	;jmp	K26
  2560                              <1> 	;
  2561                              <1> TST_ID_2:
  2562 00000E2B 8025[C6660000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2563 00000E32 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2564 00000E34 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2565 00000E36 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2566 00000E38 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2567                              <1> 	; 24/12/2021
  2568                              <1> 	;jne	K26
  2569                              <1> 	;
  2570                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2571 00000E3A F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2572 00000E3D 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2573 00000E3F 800D[C3660000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2574 00000E46 E817050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2575                              <1> KX_BIT:
  2576 00000E4B 800D[C6660000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2577 00000E52 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2578                              <1> 	;
  2579                              <1> NOT_ID:
  2580 00000E57 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2581 00000E59 750E                <1> 	jne	short TEST_E1
  2582 00000E5B 800D[C6660000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2583 00000E62 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2584                              <1> 	; 24/12/2021
  2585 00000E64 E9DA010000          <1> 	jmp	K26A	
  2586                              <1> TEST_E1:	
  2587 00000E69 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2588 00000E6B 750C                <1> 	jne	short NOT_HC
  2589 00000E6D 800D[C6660000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2590 00000E74 E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2591                              <1> 	;
  2592                              <1> NOT_HC:
  2593 00000E79 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2594 00000E7B F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2595 00000E7E 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2596                              <1> 	;
  2597 00000E80 BF[AE650000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2598 00000E85 AE                  <1> 	scasb
  2599                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2600                              <1> 	; 24/12/2021
  2601 00000E86 7458                <1> 	je	short K16B
  2602 00000E88 AE                  <1> 	scasb
  2603 00000E89 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2604 00000E8B EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2605                              <1> 	; 24/12/2021
  2606                              <1> 	;jmp	K26
  2607                              <1> 	;
  2608                              <1> NOT_LC_E0:
  2609 00000E8D F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2610 00000E90 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2611 00000E92 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2612 00000E97 BF[AC650000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2613 00000E9C F2AE                <1> 	repne	scasb			; CHECK IT
  2614 00000E9E 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2615                              <1> 	; 24/12/2021
  2616                              <1> 	;je	K26A			
  2617                              <1> 	;
  2618 00000EA0 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2619 00000EA2 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2620                              <1> 	; 24/12/2021
  2621                              <1> 	;jne	K26
  2622 00000EA4 F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2623 00000EA7 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2624                              <1> 	; 24/12/2021
  2625                              <1> 	;jnz	K26
  2626                              <1>         ; 20/02/2015 
  2627 00000EA9 F605[C4660000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2628 00000EB0 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2629                              <1> 	; 24/12/2021
  2630                              <1> 	;jnz	K26
  2631 00000EB2 E9D2020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2632                              <1> 	;
  2633                              <1> 	;-----	TEST FOR SYSTEM KEY
  2634                              <1> T_SYS_KEY:
  2635 00000EB7 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2636 00000EB9 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2637                              <1> 	;
  2638 00000EBB F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2639 00000EBE 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2640                              <1> 	;
  2641 00000EC0 F605[C4660000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2642 00000EC7 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2643                              <1> 	;jnz	K26			
  2644                              <1> 	;
  2645 00000EC9 800D[C4660000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2646 00000ED0 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2647 00000ED2 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2648                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2649 00000ED4 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2650 00000ED6 E82C040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2651                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2652                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2653                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2654                              <1> 	;INT	15H			; USER INTERRUPT	
  2655 00000EDB E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2656                              <1> 	;
  2657 00000EE0 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2658                              <1> 	;
  2659                              <1> K16C:
  2660 00000EE5 8025[C4660000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2661 00000EEC B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2662 00000EEE E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2663                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2664                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2665                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2666                              <1> 	;
  2667                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2668                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2669                              <1> 	;INT	15H			; USER INTERRUPT
  2670                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2671                              <1> 	;
  2672 00000EF0 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2673                              <1> 	;
  2674                              <1> 	;-----	TEST FOR SHIFT KEYS
  2675                              <1> K16A:
  2676 00000EF5 8A1D[C3660000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2677 00000EFB BF[A8650000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2678 00000F00 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2679 00000F05 F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2680 00000F07 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2681                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2682                              <1> 	; 24/12/2021
  2683 00000F09 7405                <1> 	je	short K17
  2684 00000F0B E914010000          <1> 	jmp	K25
  2685                              <1> 	;
  2686                              <1> 	;------	SHIFT KEY FOUND
  2687                              <1> K17:
  2688 00000F10 81EF[A9650000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2689 00000F16 8AA7[B0650000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2690 00000F1C B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2691 00000F1E A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2692                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2693                              <1> 	; 24/12/2021
  2694 00000F20 7405                <1> 	jz	short K17C
  2695 00000F22 E999000000          <1> 	jmp	K23
  2696                              <1> 	;
  2697                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2698                              <1> K17C:
  2699 00000F27 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2700 00000F2A 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2701                              <1> 	;
  2702                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2703 00000F2C 0825[C3660000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2704 00000F32 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2705 00000F34 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2706                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2707                              <1> 	; 24/12/2021
  2708 00000F36 E901010000          <1> 	jmp	K26
  2709                              <1> K17D:
  2710 00000F3B F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2711 00000F3E 740B                <1> 	jz 	short K17E		; NO, JUMP
  2712 00000F40 0825[C6660000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2713 00000F46 E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2714                              <1> K17E:
  2715 00000F4B D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2716 00000F4D 0825[C4660000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2717 00000F53 E9E4000000          <1> 	jmp	K26
  2718                              <1> 	;
  2719                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2720                              <1> K18:					; SHIFT-TOGGLE
  2721 00000F58 F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2722 00000F5B 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2723                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2724                              <1> 	; 24/12/2021
  2725 00000F5D E9C2000000          <1> 	jmp	K25
  2726                              <1> K18A:
  2727 00000F62 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2728 00000F64 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2729 00000F66 F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2730 00000F69 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2731                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2732                              <1> 	; 24/12/2021
  2733 00000F6B E9B4000000          <1> 	jmp	K25
  2734                              <1> K18B:
  2735 00000F70 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2736 00000F73 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2737                              <1> K19:	
  2738 00000F75 F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2739 00000F78 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2740 00000F7A F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2741 00000F7D 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2742                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2743 00000F7F 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2744 00000F81 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2745                              <1> K21:					; MIGHT BE NUMERIC
  2746 00000F86 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2747 00000F89 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2748                              <1> 	;
  2749                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2750 00000F8B 8425[C4660000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2751                              <1> 	;jnz	K26
  2752                              <1> 	; 24/12/2021
  2753 00000F91 7405                <1> 	jz	short K22A
  2754 00000F93 E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2755                              <1> K22A:
  2756 00000F98 0825[C4660000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2757 00000F9E 3025[C3660000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2758                              <1> 	;
  2759                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2760 00000FA4 F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2761 00000FA7 7407                <1> 	jz	short K22B		; GO IF NOT
  2762                              <1> 	;
  2763                              <1> 	; 24/12/2021
  2764                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2765 00000FA9 50                  <1> 	push	eax
  2766 00000FAA E8B3030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2767                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2768 00000FAF 58                  <1> 	pop	eax
  2769                              <1> K22B:
  2770 00000FB0 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2771                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2772                              <1> 	; 24/12/2021
  2773 00000FB2 7405                <1> 	je	short K22C
  2774 00000FB4 E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2775                              <1> K22C:
  2776 00000FB9 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2777 00000FBB E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2778                              <1> 	;
  2779                              <1> 	;-----	BREAK SHIFT FOUND
  2780                              <1> K23:					; BREAK-SHIFT-FOUND
  2781 00000FC0 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2782 00000FC3 F6D4                <1> 	not	ah			; INVERT MASK
  2783 00000FC5 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2784 00000FC7 2025[C3660000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2785 00000FCD 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2786 00000FD0 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2787                              <1> 	;
  2788 00000FD2 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2789 00000FD5 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2790 00000FD7 2025[C6660000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2791 00000FDD EB08                <1> 	jmp	short K23B		; CONTINUE
  2792                              <1> K23A:
  2793 00000FDF D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2794 00000FE1 2025[C4660000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2795                              <1> K23B:
  2796 00000FE7 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2797 00000FE9 A0[C6660000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2798 00000FEE D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2799 00000FF0 0A05[C4660000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2800 00000FF6 D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2801 00000FF8 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2802 00000FFA 0805[C3660000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2803 00001000 88E0                <1> 	mov	al, ah
  2804                              <1> K23D:
  2805 00001002 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2806 00001004 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2807                              <1> 	;	
  2808                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2809 00001006 A0[C7660000]        <1> 	mov	al, [ALT_INPUT]
  2810 0000100B B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2811 0000100D 8825[C7660000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2812 00001013 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2813 00001015 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2814 00001017 E9B4020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2815                              <1> 	;
  2816                              <1> K24:					; BREAK-TOGGLE
  2817 0000101C 2025[C4660000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2818 00001022 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2819                              <1> 	;
  2820                              <1> 	;-----	TEST FOR HOLD STATE
  2821                              <1> 					; AL, AH = SCAN CODE
  2822                              <1> K25:					; NO-SHIFT-FOUND
  2823 00001024 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2824 00001026 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2825 00001028 F605[C4660000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2826 0000102F 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2827 00001031 3C45                <1> 	cmp	al, NUM_KEY
  2828 00001033 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2829 00001035 8025[C4660000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2830                              <1> 	;
  2831                              <1> K26:
  2832 0000103C 8025[C6660000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2833                              <1> K26A:					; INTERRUPT-RETURN
  2834 00001043 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2835 00001044 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2836 00001046 E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2837                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2838 00001048 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2839 0000104A E8B8020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2840                              <1> K27A:
  2841 0000104F FA                  <1> 	cli				; DISABLE INTERRUPTS
  2842 00001050 07                  <1> 	pop	es			; RESTORE REGISTERS
  2843 00001051 1F                  <1> 	pop	ds
  2844 00001052 5F                  <1> 	pop	edi
  2845 00001053 5E                  <1> 	pop	esi
  2846 00001054 5A                  <1> 	pop	edx
  2847 00001055 59                  <1> 	pop	ecx
  2848 00001056 5B                  <1> 	pop	ebx
  2849 00001057 58                  <1> 	pop	eax
  2850                              <1> 	;pop	ebp
  2851 00001058 CF                  <1> 	iret				; RETURN
  2852                              <1> 
  2853                              <1> 	;-----	NOT IN	HOLD STATE
  2854                              <1> K28:					; NO-HOLD-STATE
  2855 00001059 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2856 0000105B 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2857                              <1> 	;
  2858 0000105D F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2859 00001060 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2860                              <1>         ; 24/12/2021
  2861                              <1> 	;jz      K38
  2862                              <1> 	;
  2863 00001062 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2864 00001065 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2865                              <1> 	; 28/02/2015
  2866 00001067 F605[C4660000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2867 0000106E 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2868                              <1> 	; 24/12/2021
  2869                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2870                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2871 00001070 E9CD000000          <1> K28A:	jmp	K38
  2872                              <1> 	;
  2873                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2874                              <1> K29:					; TEST-RESET
  2875 00001075 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2876 00001078 740B                <1> 	jz	short K31		; NO_RESET
  2877 0000107A 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2878 0000107C 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2879                              <1> 	;
  2880                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2881                              <1>  	; 26/08/2014
  2882                              <1> cpu_reset:
  2883                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2884                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2885 0000107E B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2886 00001080 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2887                              <1> khere:
  2888 00001082 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2889 00001083 EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2890                              <1> 
  2891                              <1> 	;
  2892                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2893                              <1> K31:					; NO-RESET
  2894 00001085 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2895 00001087 7507                <1> 	jne	short K311		; NOT THERE
  2896 00001089 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2897 0000108B E932020000          <1>         jmp     K57                     ; BUFFER_FILL
  2898                              <1> K311:
  2899 00001090 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2900 00001092 7509                <1> 	jne	short K312		; NOT THERE
  2901 00001094 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2902 00001098 E925020000          <1>         jmp     K57                     ; BUFFER_FILL
  2903                              <1> K312:
  2904 0000109D 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2905 0000109F 7471                <1>         je	short K37B              ; GO PROCESS
  2906 000010A1 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2907 000010A3 746D                <1>         je	short K37B              ; GO PROCESS
  2908                              <1> 	;
  2909                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2910                              <1> K32:					; ALT-KEY-PAD
  2911 000010A5 BF[84650000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2912 000010AA B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2913 000010AF F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2914 000010B1 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2915 000010B3 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2916                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2917                              <1> 	; 24/12/2021
  2918 000010B6 751C                <1> 	jnz	short K32B
  2919 000010B8 81EF[85650000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2920 000010BE A0[C7660000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2921 000010C3 B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2922 000010C5 F6E4                <1> 	mul	ah
  2923 000010C7 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2924 000010CA A2[C7660000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2925                              <1> K32A:
  2926 000010CF E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2927                              <1> K32B:
  2928                              <1> 	; 24/12/2021
  2929 000010D4 EB66                <1> 	jmp	K37C
  2930                              <1> 	;
  2931                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2932                              <1> K33:					; NO-ALT-KEYPAD
  2933 000010D6 C605[C7660000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2934 000010DD B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2935 000010E2 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2936 000010E4 744F                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2937                              <1> 	;
  2938                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2939                              <1> K34:					; ALT-TOP-ROW
  2940 000010E6 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2941 000010E8 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2942 000010EA 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2943 000010EC 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2944 000010EE 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2945 000010F1 EB42                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2946                              <1> 	;
  2947                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2948                              <1> K35:					; ALT-FUNCTION
  2949 000010F3 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2950 000010F5 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2951 000010F7 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2952 000010F9 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2953 000010FB 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2954 000010FE EB35                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2955                              <1> K35A:
  2956 00001100 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2957 00001103 7425                <1> 	jz	short K37		; NO, JUMP
  2958 00001105 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2959 00001107 7510                <1>         jne     short K35B              ; NOT THERE
  2960 00001109 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2961 0000110D E9B0010000          <1> 	jmp	K57			; BUFFER FILL
  2962                              <1> K37B:
  2963 00001112 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  2964 00001114 E9A9010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  2965                              <1> K35B:
  2966 00001119 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  2967 0000111B 741F                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  2968 0000111D 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  2969 0000111F 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  2970                              <1>         ; 24/12/2021
  2971                              <1> 	;jne	K26
  2972 00001121 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  2973 00001125 E998010000          <1> 	jmp	K57			; BUFFER FILL
  2974                              <1> K37:
  2975 0000112A 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  2976 0000112C 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  2977 0000112E 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  2978 00001130 779D                <1>         ja	short K32A		; IF SO, IGNORE
  2979                              <1> 	; 13/06/2022
  2980                              <1>         ;ja	K26
  2981 00001132 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  2982                              <1> K37A:
  2983 00001135 B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  2984 00001137 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  2985                              <1> K37C:
  2986 0000113C 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  2987 0000113E 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  2988 00001140 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  2989                              <1> 	;
  2990                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  2991                              <1> K38:					; NOT-ALT-SHIFT
  2992                              <1> 					; BL STILL HAS SHIFT FLAGS
  2993 00001142 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  2994 00001145 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  2995                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  2996                              <1> 	; 24/12/2021
  2997 00001147 E9AB000000          <1> 	jmp	K44
  2998                              <1> 	;
  2999                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3000                              <1> 	;-----	TEST FOR BREAK
  3001                              <1> K38A:
  3002 0000114C 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3003 0000114E 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3004 00001150 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3005 00001153 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3006 00001155 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3007 00001158 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3008                              <1> K38B:
  3009 0000115A 8B1D[D0660000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3010 00001160 891D[D4660000]      <1> 	mov	[BUFFER_TAIL], ebx
  3011 00001166 C605[C2660000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3012                              <1> 	;
  3013                              <1> 	;-----	ENABLE KEYBOARD
  3014 0000116D B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3015 0000116F E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3016                              <1> 	;
  3017                              <1> 	; CTRL+BREAK code here !!!
  3018                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3019                              <1> 	; 17/10/2015	
  3020 00001174 E853220000          <1> 	call	ctrlbrk ; control+break subroutine
  3021                              <1> 	;
  3022                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3023                              <1> 	; 24/12/2021
  3024 00001179 29C0                <1> 	sub	eax, eax
  3025 0000117B E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3026                              <1> 	;
  3027                              <1> 	;-----	TEST FOR PAUSE
  3028                              <1> K39:					; NO_BREAK
  3029 00001180 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3030 00001183 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3031 00001185 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3032 00001187 7533                <1> 	jne	short K41		; NO-PAUSE
  3033                              <1> K39P:
  3034 00001189 800D[C4660000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3035                              <1> 	;
  3036                              <1> 	;-----	ENABLE KEYBOARD
  3037 00001190 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3038 00001192 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3039                              <1> K39A:
  3040 00001197 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3041 00001199 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3042                              <1> 	;
  3043                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3044 0000119B 803D[C0660000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3045 000011A2 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3046 000011A4 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3047 000011A8 A0[C1660000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3048 000011AD EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3049                              <1> 	;
  3050                              <1> K40:					; PAUSE-LOOP
  3051 000011AE F605[C4660000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3052 000011B5 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3053                              <1> 	;
  3054 000011B7 E98CFEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3055                              <1>         ;
  3056                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3057                              <1> K41:					; NO-PAUSE
  3058 000011BC 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3059 000011BE 7513                <1> 	jne	short K42		; NOT-KEY-55
  3060 000011C0 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3061 000011C3 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3062 000011C5 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3063 000011C8 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3064                              <1> K41A:	
  3065 000011CA 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3066 000011CE E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3067                              <1> 	;
  3068                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3069                              <1> K42:					; NOT-KEY-55
  3070 000011D3 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3071 000011D5 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3072 000011D7 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3073 000011D9 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3074 000011DB F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3075 000011DE 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3076 000011E0 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3077 000011E4 E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3078                              <1> K42A:
  3079                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3080 000011E9 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3081                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3082                              <1> 	;;jb	K56 ; 20/02/2015
  3083                              <1> 	;;jmp	K64 ; 20/02/2015
  3084                              <1> K42B:
  3085 000011EB BB[B8650000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3086                              <1> 	;;jmp	K64
  3087                              <1> 	;jb	K56 ;; 20/02/2015	
  3088                              <1> 	; 24/12/2021
  3089 000011F0 7267                <1> 	jb	short K45F
  3090 000011F2 E9B9000000          <1> 	jmp	K64	
  3091                              <1>         ;
  3092                              <1> 	;-----	NOT IN CONTROL SHIFT
  3093                              <1> K44:					; NOT-CTL-SHIFT
  3094 000011F7 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3095 000011F9 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3096 000011FB F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3097 000011FE 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3098 00001200 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3099 00001203 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3100 00001205 EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3101                              <1> K44A:
  3102 00001207 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3103 0000120A 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3104                              <1> 	;
  3105                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3106                              <1> K44B:
  3107 0000120C B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3108 0000120E E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3109 00001213 B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3110 00001215 E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3111                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3112                              <1> 	;PUSH 	BP			; SAVE POINTER
  3113                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3114                              <1> 	;POP	BP			; RESTORE POINTER
  3115 00001217 8025[C6660000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3116 0000121E E925FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3117                              <1> 	;
  3118                              <1> 	;-----	HANDLE IN-CORE KEYS
  3119                              <1> K45:					; NOT-PRINT-SCREEN
  3120 00001223 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3121 00001225 7734                <1> 	ja	short K46		; JUMP IF NOT
  3122 00001227 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3123 00001229 7505                <1> 	jne	short K45A		; NO, JUMP
  3124 0000122B F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3125 0000122E 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3126                              <1> K45A:
  3127 00001230 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3128 00001235 BF[8E650000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3129 0000123A F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3130                              <1> 		; 20/02/2015
  3131 0000123C 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3132                              <1> 	;
  3133 0000123E F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3134 00001241 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3135                              <1> K45B:
  3136 00001243 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3137 00001246 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3138                              <1> 					; NO, LOWERCASE
  3139                              <1> K45C:
  3140 00001248 BB[10660000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3141 0000124D EB51                <1> 	jmp	short K56	
  3142                              <1> K45D:					; ALMOST-CAPS-STATE
  3143 0000124F F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3144 00001252 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3145                              <1> K45E:
  3146 00001254 BB[68660000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3147 00001259 EB45                <1> K45F:	jmp	short K56
  3148                              <1> 	;
  3149                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3150                              <1> K46:					; NOT IN-CORE AREA
  3151 0000125B 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3152                              <1> 	;ja	short K47		; JUMP IF NOT
  3153                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3154 0000125D 7635                <1> 	jna	short K53		
  3155                              <1> 	;
  3156                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3157                              <1> K47:					; NOT F1 - F10
  3158 0000125F 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3159 00001261 772D                <1> 	ja	short K52		; JUMP IF NOT
  3160                              <1> 	;
  3161                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3162                              <1> K48:
  3163 00001263 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3164 00001265 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3165 00001267 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3166 00001269 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3167 0000126B F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3168 0000126E 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3169                              <1> 	;		
  3170 00001270 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3171 00001273 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3172 00001275 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3173                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3174 00001278 75DA                <1> 	jnz	short K45E
  3175                              <1> 	;
  3176                              <1> 	;-----	BASE CASE FOR KEYPAD
  3177                              <1> K49:					
  3178 0000127A 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3179 0000127C 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3180 0000127E B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3181 00001280 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3182                              <1> K49A:
  3183 00001282 BB[10660000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3184 00001287 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3185                              <1> 	;
  3186                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3187                              <1> K50:					; ALMOST-NUM-STATE
  3188 00001289 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3189 0000128C 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3190 0000128E EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3191                              <1> 	;
  3192                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3193                              <1> K52:					; NOT A NUMPAD KEY
  3194 00001290 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3195                              <1> 	;jne	short K53		; JUMP IF NOT
  3196                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3197 00001292 74AF                <1> 	je	short K45B		
  3198                              <1> 	;
  3199                              <1> 	;-----	MUST BE F11 OR F12 
  3200                              <1> K53:					; F1 - F10 COME HERE, TOO
  3201 00001294 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3202 00001297 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3203                              <1> 		; 20/02/2015 
  3204 00001299 BB[68660000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3205 0000129E EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3206                              <1> 	;
  3207                              <1> 	;-----	TRANSLATE THE CHARACTER
  3208                              <1> K56:					; TRANSLATE-CHAR
  3209 000012A0 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3210 000012A2 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3211 000012A3 F605[C6660000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3212 000012AA 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3213 000012AC B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3214 000012AE EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3215                              <1> 	;
  3216                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3217                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3218 000012B0 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3219 000012B2 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3220 000012B3 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3221 000012B5 B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3222 000012B7 F605[C6660000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3223 000012BE 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3224 000012C0 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3225                              <1> 	;
  3226                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3227                              <1> K57:					; BUFFER_FILL
  3228 000012C2 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3229 000012C4 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3230                              <1> 	; 24/12/2021
  3231                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3232 000012C6 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3233                              <1> 	; 24/12/2021
  3234 000012C9 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3235                              <1> 	;je	K26			; INTERRUPT_RETURN
  3236                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3237 000012CB E96CFDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3238                              <1> K61:					; NOT-CAPS-STATE
  3239 000012D0 8B1D[D4660000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3240 000012D6 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3241 000012D8 E8AEFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3242 000012DD 3B1D[D0660000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3243 000012E3 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3244 000012E5 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3245 000012E8 891D[D4660000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3246 000012EE E949FDFFFF          <1> 	jmp	K26
  3247                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3248                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3249                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3250                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3251                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3252                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3253                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3254                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3255                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3256                              <1> 	;;jmp   K27                    
  3257                              <1> 	;
  3258                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3259                              <1> K62:
  3260 000012F3 B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3261 000012F5 E620                <1> 	out	INTA00, al
  3262 000012F7 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3263 000012FB B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3264 000012FD E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3265 00001302 E941FDFFFF          <1> 	jmp     K27			; EXIT   
  3266                              <1> 
  3267                              <1> SHIP_IT:
  3268                              <1> 	;---------------------------------------------------------------------------------
  3269                              <1> 	; SHIP_IT
  3270                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3271                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3272                              <1> 	;---------------------------------------------------------------------------------
  3273                              <1> 	;
  3274                              <1> 	;push	ax			; SAVE DATA TO SEND
  3275                              <1> 	; 24/12/2021
  3276 00001307 50                  <1> 	push	eax
  3277                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3278 00001308 FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3279                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3280 00001309 B900000100          <1> 	mov	ecx, 10000h			
  3281                              <1> S10:
  3282 0000130E E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3283 00001310 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3284 00001312 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3285                              <1> 
  3286                              <1> 	;pop	ax			; GET DATA TO SEND
  3287                              <1> 	; 24/12/2021
  3288 00001314 58                  <1> 	pop	eax
  3289 00001315 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3290 00001317 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3291 00001318 C3                  <1> 	retn				; RETURN TO CALLER
  3292                              <1> 
  3293                              <1> SND_DATA:
  3294                              <1> 	; ---------------------------------------------------------------------------------
  3295                              <1> 	; SND_DATA
  3296                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3297                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3298                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3299                              <1> 	; ---------------------------------------------------------------------------------
  3300                              <1> 	;
  3301                              <1> 	;push	ax			; SAVE REGISTERS
  3302                              <1> 	;push	bx
  3303                              <1> 	; 24/12/2021
  3304 00001319 50                  <1> 	push	eax
  3305 0000131A 53                  <1> 	push	ebx
  3306 0000131B 51                  <1> 	push	ecx
  3307 0000131C 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3308 0000131E B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3309                              <1> SD0:
  3310 00001320 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3311 00001321 8025[C5660000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3312                              <1> 	;
  3313                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3314 00001328 B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3315                              <1> SD5:
  3316 0000132D E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3317 0000132F A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3318 00001331 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3319                              <1> 	;
  3320 00001333 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3321 00001335 E660                <1> 	out	PORT_A, al		; SEND BYTE
  3322 00001337 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3323                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3324 00001338 B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3325                              <1> SD1:
  3326 0000133D F605[C5660000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3327 00001344 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3328 00001346 E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3329                              <1> SD2:
  3330 00001348 FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3331 0000134A 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3332 0000134C 800D[C5660000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3333 00001353 EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3334                              <1> SD3:
  3335 00001355 F605[C5660000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3336 0000135C 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3337                              <1> SD4:	
  3338 0000135E 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3339                              <1> 	;pop	bx
  3340                              <1> 	;pop	ax
  3341                              <1> 	; 24/12/2021
  3342 0000135F 5B                  <1> 	pop	ebx
  3343 00001360 58                  <1> 	pop	eax
  3344 00001361 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3345                              <1> 
  3346                              <1> SND_LED:
  3347                              <1> 	; ---------------------------------------------------------------------------------
  3348                              <1> 	; SND_LED
  3349                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3350                              <1> 	;
  3351                              <1> 	;----------------------------------------------------------------------------------
  3352                              <1> 	;
  3353 00001362 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3354 00001363 F605[C5660000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3355 0000136A 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3356                              <1> 	;
  3357 0000136C 800D[C5660000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3358 00001373 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3359 00001375 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3360 00001377 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3361                              <1> SND_LED1:
  3362 00001379 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3363 0000137A F605[C5660000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3364 00001381 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3365                              <1> 	;
  3366 00001383 800D[C5660000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3367                              <1> SL0:
  3368 0000138A B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3369 0000138C E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3370 00001391 FA                  <1> 	cli
  3371 00001392 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3372 00001397 8025[C5660000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3373 0000139E 0805[C5660000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3374 000013A4 F605[C5660000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3375 000013AB 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3376                              <1> 	;
  3377 000013AD E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3378 000013B2 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3379 000013B3 F605[C5660000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3380 000013BA 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3381                              <1> SL2:
  3382 000013BC B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3383 000013BE E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3384 000013C3 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3385                              <1> SL3:
  3386 000013C4 8025[C5660000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3387                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3388 000013CB FB                  <1> 	sti				; ENABLE INTERRUPTS
  3389 000013CC C3                  <1> 	retn				; RETURN TO CALLER
  3390                              <1> 
  3391                              <1> MAKE_LED:
  3392                              <1> 	;---------------------------------------------------------------------------------
  3393                              <1> 	; MAKE_LED
  3394                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3395                              <1> 	;	THE MODE INDICATORS.
  3396                              <1> 	;---------------------------------------------------------------------------------
  3397                              <1> 	;
  3398                              <1> 	;push 	cx			; SAVE CX
  3399 000013CD A0[C3660000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3400 000013D2 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3401                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3402                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3403 000013D4 C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3404 000013D7 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3405                              <1> 	;pop	cx
  3406 000013D9 C3                  <1> 	retn				; RETURN TO CALLER
  3407                              <1> 
  3408                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3409                              <1> 
  3410                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1830                                  
  1831                                  %include 'video.inc' ; 07/03/2015
  1832                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - VIDEO.INC
  1833                              <1> ; Last Modification: 14/06/2022
  1834                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1835                              <1> ;
  1836                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1837                              <1> 
  1838                              <1> ; 14/06/2022
  1839                              <1> ; 25/02/2022
  1840                              <1> ; 02/02/2022 (simplified scroll up)
  1841                              <1> ; 16/01/2016
  1842                              <1> ; 30/06/2015
  1843                              <1> ; 27/06/2015
  1844                              <1> ; 11/03/2015
  1845                              <1> ; 02/09/2014
  1846                              <1> ; 30/08/2014
  1847                              <1> ; VIDEO FUNCTIONS
  1848                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1849                              <1> 
  1850                              <1> write_tty:
  1851                              <1> 	; 02/02/2022
  1852                              <1> 	; 13/08/2015
  1853                              <1> 	; 02/09/2014
  1854                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1855                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1856                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1857                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1858                              <1> 	;
  1859                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1860                              <1> 	;	   AL = Character to be written
  1861                              <1> 	;	   EBX = Video Page (0 to 7)
  1862                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1863                              <1> 
  1864                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1865                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1866                              <1> 
  1867                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1868                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1869                              <1> ;
  1870                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1871                              <1> ;
  1872                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1873                              <1> ;										:
  1874                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1875                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1876                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1877                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1878                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1879                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1880                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1881                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1882                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1883                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1884                              <1> ;   THE 0 COLOR IS USED.							:
  1885                              <1> ;   ENTRY --									:
  1886                              <1> ;     (AH) = CURRENT CRT MODE							:
  1887                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1888                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1889                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1890                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1891                              <1> ;   EXIT -- 									:
  1892                              <1> ;     ALL REGISTERS SAVED							:
  1893                              <1> ;--------------------------------------------------------------------------------
  1894                              <1> 
  1895 000013DA FA                  <1> 	cli
  1896                              <1> 	;
  1897                              <1> 	; READ CURSOR (04/12/2013)
  1898                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1899 000013DB 08FF                <1> 	or	bh, bh
  1900                              <1> 	;jnz	beeper
  1901                              <1> 	; 02/02/2022
  1902 000013DD 7405                <1> 	jz	short u14
  1903 000013DF E992000000          <1> 	jmp	beeper
  1904                              <1> u14:
  1905                              <1> 	; 02/02/2022
  1906                              <1> 	;; 01/09/2014
  1907                              <1> 	;cmp	byte [CRT_MODE], 3
  1908                              <1> 	;je	short m3
  1909                              <1> 	;;
  1910                              <1> 	;call	set_mode
  1911                              <1> m3:
  1912 000013E4 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1913                              <1> 	;shl	si, 1
  1914                              <1> 	; 02/02/2022
  1915 000013E6 D1E6                <1> 	shl	esi, 1
  1916 000013E8 81C6[B66C0000]      <1> 	add	esi, cursor_posn
  1917 000013EE 668B16              <1> 	mov	dx, [esi]
  1918                              <1> 	;
  1919                              <1> 	; dx now has the current cursor position
  1920                              <1> 	;
  1921 000013F1 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1922 000013F3 7647                <1> 	jbe	short u8
  1923                              <1> 	;
  1924                              <1> 	; write the char to the screen
  1925                              <1> u0:	
  1926                              <1> 	; ah = attribute/color
  1927                              <1> 	; al = character
  1928                              <1> 	; bl = video page number (0 to 7)
  1929                              <1> 	; bh = 0
  1930                              <1> 	;
  1931 000013F5 E8D2010000          <1> 	call	write_c_current
  1932                              <1> 	;
  1933                              <1> 	; position the cursor for next char
  1934 000013FA FEC2                <1> 	inc	dl		; next column
  1935                              <1> 	;cmp	dl, [CRT_COLS]
  1936 000013FC 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1937                              <1>         ;jne	set_cpos
  1938                              <1> 	; 02/02/2022
  1939 000013FF 7405                <1> 	je	short u13
  1940 00001401 E9DE000000          <1> 	jmp	set_cpos
  1941                              <1> u13:
  1942 00001406 B200                <1> 	mov	dl, 0		; column = 0
  1943                              <1> u10:				; (line feed found)
  1944 00001408 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1945 0000140B 7228                <1> 	jb 	short u6
  1946                              <1> 	;
  1947                              <1> 	; scroll required
  1948                              <1> u1:	
  1949                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1950 0000140D E8D2000000          <1> 	call	set_cpos
  1951                              <1> 	;
  1952                              <1> 	; determine value to fill with during scroll
  1953                              <1> u2:
  1954                              <1> 	; READ_AC_CURRENT		:
  1955                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1956                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1957                              <1> 	;
  1958                              <1> 	; INPUT				
  1959                              <1> 	;	(AH) = CURRENT CRT MODE
  1960                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  1961                              <1> 	;	(DS) = DATA SEGMENT
  1962                              <1> 	;	(ES) = REGEN SEGMENT
  1963                              <1> 	; OUTPUT			
  1964                              <1> 	;	(AL) = CHARACTER READ
  1965                              <1> 	;	(AH) = ATTRIBUTE READ
  1966                              <1> 	;
  1967                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  1968                              <1> 	;
  1969                              <1> 	; bl = video page number
  1970                              <1> 	;
  1971 00001412 E829010000          <1> 	call	find_position	; get regen location and port address
  1972                              <1> 	; dx = status port
  1973                              <1> 	; esi = cursor location/address
  1974                              <1> p11:
  1975 00001417 FB                  <1> 	sti			; enable interrupts
  1976 00001418 90                  <1> 	nop			; allow for small interupts window
  1977 00001419 FA                  <1> 	cli			; blocks interrupts for single loop
  1978 0000141A EC                  <1> 	in	al, dx		; get status from adapter
  1979 0000141B A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  1980 0000141D 75F8                <1> 	jnz	short p11	; wait until it is
  1981                              <1> p12:				; now wait for either retrace high
  1982 0000141F EC                  <1> 	in	al, dx		; get status
  1983 00001420 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  1984 00001422 74FB                <1> 	jz	short p12	; wait until either is active	
  1985                              <1> p13:
  1986 00001424 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  1987 0000142A 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  1988                              <1> 	;
  1989                              <1> 	; al = character, ah = attribute
  1990                              <1> 	;
  1991 0000142D FB                  <1> 	sti
  1992                              <1> 	; bl = video page number 	
  1993                              <1> u3:
  1994                              <1> 	;;mov	ax, 0601h 	; scroll one line
  1995                              <1> 	;;sub	cx, cx		; upper left corner
  1996                              <1> 	;;mov	dh, 25-1 	; lower right row
  1997                              <1> 	;;;mov	dl, [CRT_COLS]
  1998                              <1> 	;mov	dl, 80		; lower right column	
  1999                              <1> 	;;dec	dl
  2000                              <1> 	;;mov	dl, 79
  2001                              <1> 
  2002                              <1> 	;;call	scroll_up	; 04/12/2013
  2003                              <1> 	;;; 11/03/2015
  2004                              <1> 	; 02/09/2014
  2005                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2006                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2007                              <1> 	; 11/03/2015
  2008                              <1> 	;sub	cx, cx
  2009                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2010                              <1> 	;
  2011                              <1> 	; 02/02/2022 (simplied scroll up)
  2012                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2013                              <1> 	;
  2014 0000142E B001                <1> 	mov	al, 1		; scroll 1 line up
  2015                              <1> 		; ah = attribute
  2016 00001430 E935010000          <1> 	jmp	scroll_up
  2017                              <1> ;u4:
  2018                              <1> 	;;int	10h		; video-call return
  2019                              <1> 				; scroll up the screen
  2020                              <1> 				; tty return
  2021                              <1> ;u5:
  2022                              <1> 	;retn			; return to the caller
  2023                              <1> 
  2024                              <1> u6:				; set-cursor-inc
  2025 00001435 FEC6                <1> 	inc	dh		; next row
  2026                              <1> 				; set cursor
  2027                              <1> ;u7:					
  2028                              <1> 	;;mov	ah, 02h
  2029                              <1> 	;;jmp	short u4 	; establish the new cursor
  2030                              <1> 	;call	set_cpos
  2031                              <1> 	;jmp 	short u5
  2032 00001437 E9A8000000          <1> 	jmp     set_cpos
  2033                              <1> 
  2034                              <1> 	; check for control characters
  2035                              <1> u8:
  2036 0000143C 7434                <1> 	je	short u9
  2037 0000143E 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2038 00001440 74C6                <1> 	je	short u10
  2039 00001442 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2040 00001444 7430                <1> 	je	short u11
  2041 00001446 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2042                              <1> 	;jne	short u0
  2043 00001448 7420                <1> 	je	short bs	; 12/12/2013
  2044                              <1> 	; 12/12/2013 (tab stop)
  2045 0000144A 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2046 0000144C 75A7                <1> 	jne	short u0
  2047 0000144E 88D0                <1> 	mov	al, dl
  2048 00001450 6698                <1> 	cbw
  2049 00001452 B108                <1> 	mov	cl, 8
  2050 00001454 F6F1                <1> 	div	cl
  2051 00001456 28E1                <1> 	sub	cl, ah
  2052                              <1> ts:
  2053                              <1> 	; 02/09/2014
  2054                              <1> 	; 01/09/2014
  2055 00001458 B020                <1> 	mov	al, 20h
  2056                              <1> tsloop:
  2057                              <1> 	;push	cx
  2058                              <1> 	;push	ax
  2059                              <1> 	; 02/02/2022
  2060 0000145A 51                  <1> 	push	ecx
  2061 0000145B 50                  <1> 	push	eax
  2062 0000145C 30FF                <1> 	xor 	bh, bh
  2063                              <1> 	;mov	bl, [active_page]
  2064 0000145E E881FFFFFF          <1> 	call	m3
  2065                              <1> 	; 02/02/2022
  2066 00001463 58                  <1> 	pop	eax
  2067 00001464 59                  <1>  	pop	ecx
  2068                              <1> 	;pop	ax  ; ah = attribute/color
  2069                              <1> 	;pop	cx
  2070 00001465 FEC9                <1> 	dec	cl
  2071 00001467 75F1                <1> 	jnz	short tsloop
  2072 00001469 C3                  <1> 	retn
  2073                              <1> bs:	
  2074                              <1> 	; back space found
  2075 0000146A 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2076                              <1> 	;je	short u7 	; set_cursor
  2077 0000146C 7476                <1> 	jz	short set_cpos
  2078                              <1> 	;dec	dx     		; no -- just move it back
  2079                              <1> 	; 02/02/2022
  2080 0000146E FECA                <1> 	dec	dl
  2081                              <1> 	;jmp	short u7
  2082 00001470 EB72                <1> 	jmp	short set_cpos
  2083                              <1> 
  2084                              <1> 	; carriage return found
  2085                              <1> u9:
  2086 00001472 B200                <1> 	mov	dl, 0 		; move to first column
  2087                              <1> 	;jmp	short u7
  2088 00001474 EB6E                <1> 	jmp	short set_cpos
  2089                              <1> 
  2090                              <1> 	; line feed found
  2091                              <1> ;u10:
  2092                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2093                              <1> ;	jne	short u6 	; no, just set the cursor
  2094                              <1> ;       jmp     u1              ; yes, scroll the screen
  2095                              <1> 
  2096                              <1> beeper: 
  2097                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2098                              <1> 	; 18/01/2014
  2099                              <1> 	; 03/12/2013
  2100                              <1> 	; bell found
  2101                              <1> u11:
  2102 00001476 FB                  <1> 	sti
  2103 00001477 3A1D[C66C0000]      <1> 	cmp	bl, [active_page]
  2104 0000147D 7551                <1> 	jne	short u12	; Do not sound the beep 
  2105                              <1> 				; if it is not written on the active page
  2106 0000147F 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2107 00001483 B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2108                              <1> 	;call	beep		; sound the pod bell
  2109                              <1> 	;jmp	short u5 	; tty_return
  2110                              <1> 	;retn
  2111                              <1> 	
  2112                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2113                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2114                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2115                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2116                              <1> 
  2117                              <1> beep:
  2118                              <1> 	; 07/02/2015
  2119                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2120                              <1> 	; 18/01/2014
  2121                              <1> 	; 03/12/2013
  2122                              <1> 	;
  2123                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2124                              <1> 	;
  2125                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2126                              <1> 	;
  2127                              <1> 	; ENTRY:
  2128                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2129                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2130                              <1> 	; EXIT:			:
  2131                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2132                              <1> 
  2133 00001485 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2134 00001486 FA                  <1> 	cli			; block interrupts during update
  2135 00001487 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2136 00001489 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2137 0000148B EB00                <1> 	jmp	$+2		; I/O delay
  2138 0000148D 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2139 0000148F E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2140 00001491 EB00                <1> 	jmp	$+2		; I/O delay
  2141 00001493 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2142 00001495 E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2143 00001497 E461                <1> 	in	al, PORT_B	; get current setting of port
  2144 00001499 88C4                <1> 	mov	ah, al		; save that setting
  2145 0000149B 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2146 0000149D E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2147                              <1> 	;popf	; 18/01/2014
  2148 0000149F FB                  <1> 	sti
  2149                              <1> g7:				; 1/64 second per count (bl)
  2150 000014A0 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2151 000014A5 E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2152 000014AA FECB                <1> 	dec	bl		; (bl) length count expired?
  2153 000014AC 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2154                              <1> 	;
  2155                              <1> 	;pushf			; save interrupt status
  2156 000014AE FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2157 000014AF E461                <1> 	in	al, PORT_B	; get current port value
  2158                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2159 000014B1 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2160 000014B3 20C4                <1>         and	ah, al		; someone turned them off during beep
  2161 000014B5 88E0                <1> 	mov	al, ah		; recover value of port
  2162                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2163 000014B7 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2164 000014B9 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2165                              <1> 	;popf			; restore interrupt flag state
  2166 000014BB FB                  <1> 	sti
  2167 000014BC B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2168 000014C1 E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2169                              <1> 	;pushf			; save interrupt status
  2170 000014C6 FA                  <1> 	cli			; block interrupts during update
  2171 000014C7 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2172 000014C9 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2173 000014CB 08E0                <1> 	or	al, ah		; recover value of port_b
  2174 000014CD E661                <1> 	out	PORT_B, al	; restore speaker status
  2175 000014CF 9D                  <1> 	popf			; restore interrupt flag state
  2176                              <1> u12:	
  2177 000014D0 C3                  <1> 	retn
  2178                              <1> 
  2179                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2180                              <1> 
  2181                              <1> WAITF:
  2182                              <1> waitf:
  2183                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2184                              <1> 	; 03/12/2013
  2185                              <1> 	;
  2186                              <1> ;	push	ax		; save work register (ah)	
  2187                              <1> ;waitf1:
  2188                              <1> 				; use timer 1 output bits
  2189                              <1> ;	in	al, PORT_B	; read current counter output status
  2190                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2191                              <1> ;	cmp	al, ah		; did it just change
  2192                              <1> ;	je	short waitf1	; wait for a change in output line
  2193                              <1> ;	;
  2194                              <1> ;	mov	ah, al		; save new lflag state
  2195                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2196                              <1> ;	;
  2197                              <1> ;	pop	ax		; restore (ah)
  2198                              <1> ;	retn			; return (cx)=0
  2199                              <1> 
  2200                              <1> ; 02/02/2022
  2201                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2202                              <1> ; 17/12/2014 (dsectrm2.s)
  2203                              <1> ; WAITF
  2204                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2205                              <1> ;
  2206                              <1> ;---WAITF-----------------------------------------------------------------------
  2207                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2208                              <1> ; ENTRY:
  2209                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2210                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2211                              <1> ; EXIT:
  2212                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2213                              <1> ;	(CX) = 0	
  2214                              <1> ;-------------------------------------------------------------------------------
  2215                              <1> 
  2216                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2217                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2218                              <1> 
  2219                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2220 000014D1 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2221                              <1> 	;push	ax
  2222                              <1> 	; 16/12/2014
  2223                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2224 000014D2 D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2225                              <1> ;17/12/2014	
  2226                              <1> ;WAITF1:
  2227                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2228                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2229                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2230                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2231                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2232                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2233                              <1> 	;
  2234                              <1> 	; 17/12/2014
  2235                              <1> 	;
  2236                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2237                              <1> 	;
  2238                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2239                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2240                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2241                              <1> WR_STATE_0:
  2242 000014D4 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2243 000014D6 A810                <1> 	TEST	AL,010H
  2244 000014D8 74FA                <1> 	JZ	SHORT WR_STATE_0
  2245                              <1> WR_STATE_1:
  2246 000014DA E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2247 000014DC A810                <1> 	TEST	AL,010H
  2248 000014DE 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2249 000014E0 E2F2                <1>         LOOP    WR_STATE_0
  2250                              <1> 	;
  2251                              <1> 	;pop	ax
  2252 000014E2 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2253 000014E3 C3                  <1> 	RETn				; (CX) = 0
  2254                              <1> 
  2255                              <1> set_cpos:
  2256                              <1> 	; 14/06/2022 (Retro UNIX 386 v1, Kernel v0.2.0.20)
  2257                              <1> 	; 25/02/2022
  2258                              <1> 	; 23/02/2022
  2259                              <1> 	; 02/02/2022
  2260                              <1> 	; 27/06/2015
  2261                              <1> 	; 01/09/2014
  2262                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2263                              <1> 	;
  2264                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2265                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2266                              <1> 	;
  2267                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2268                              <1> 	;
  2269                              <1> 	; SET_CPOS
  2270                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2271                              <1> 	;	NEW X-Y VALUES PASSED
  2272                              <1> 	; INPUT
  2273                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2274                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2275                              <1> 	; OUTPUT
  2276                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2277                              <1> 	;
  2278 000014E4 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2279 000014E7 D0E0                <1>         shl     al, 1   ; word offset
  2280 000014E9 BE[B66C0000]        <1> 	mov	esi, cursor_posn
  2281 000014EE 01C6                <1>         add     esi, eax
  2282 000014F0 668916              <1> 	mov	[esi], dx ; save the pointer
  2283 000014F3 381D[C66C0000]      <1> 	cmp	[active_page], bl
  2284 000014F9 7531                <1> 	jne	short m17
  2285                              <1> 
  2286                              <1> 	; 14/06/2022	
  2287                              <1> 	;cli ; 25/02/2022
  2288                              <1> 
  2289                              <1> 	;call	m18	;h CURSOR SET
  2290                              <1> ;m17:			; SET_CPOS_RETURN
  2291                              <1> 	; 01/09/2014
  2292                              <1> 	;retn
  2293                              <1> 		; DX = row/column
  2294                              <1> m18:
  2295 000014FB E832000000          <1> 	call	position ; determine location in regen buffer	
  2296                              <1> 	;mov	cx, [CRT_START]
  2297                              <1> 	; 23/02/2022
  2298 00001500 0FB70D[B46C0000]    <1> 	movzx	ecx, word [CRT_START]
  2299 00001507 01C1                <1> 	add	ecx, eax
  2300                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2301                              <1> 			; to the start address (offset) for this page
  2302                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2303                              <1> 	; 23/02/2022
  2304 00001509 D1E9                <1> 	shr	ecx, 1
  2305 0000150B B40E                <1> 	mov	ah, 14	; register number for cursor
  2306                              <1> 	
  2307                              <1> 	; 14/06/2022
  2308                              <1> 	;call	m16	; output value to the 6845
  2309                              <1> 	;sti	; 25/02/2022
  2310                              <1> 	;retn
  2311                              <1> 
  2312                              <1> 	; 14/06/2022
  2313                              <1> 	; 25/02/2022
  2314                              <1> 	; 02/02/2022
  2315                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2316                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2317                              <1> m16:
  2318                              <1> 	; 14/06/2022
  2319 0000150D FA                  <1> 	cli	; 25/02/2022
  2320                              <1> 	;mov	dx, [addr_6845] ; address register
  2321 0000150E 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2322 00001512 88E0                <1> 	mov	al, ah	; get value
  2323 00001514 EE                  <1> 	out	dx, al	; register set
  2324                              <1> 	;inc	dx	; data register
  2325                              <1> 	; 02/02/2022
  2326 00001515 FEC2                <1> 	inc	dl
  2327 00001517 EB00                <1> 	jmp	$+2	; i/o delay
  2328 00001519 88E8                <1> 	mov	al, ch	; data
  2329 0000151B EE                  <1> 	out	dx, al	
  2330                              <1> 	;dec	dx
  2331                              <1> 	; 02/02/2022	
  2332 0000151C FECA                <1> 	dec	dl
  2333 0000151E 88E0                <1> 	mov	al, ah
  2334 00001520 FEC0                <1> 	inc	al	; point to other data register
  2335 00001522 EE                  <1> 	out	dx, al	; set for second register
  2336                              <1> 	;inc	dx
  2337                              <1> 	; 02/02/2022
  2338 00001523 FEC2                <1> 	inc	dl
  2339 00001525 EB00                <1> 	jmp	$+2	; i/o delay
  2340 00001527 88C8                <1> 	mov	al, cl	; second data value
  2341 00001529 EE                  <1> 	out	dx, al
  2342                              <1> 	; 14/06/2022
  2343 0000152A FB                  <1> 	sti	; 25/02/2022
  2344                              <1> ;m17:
  2345 0000152B C3                  <1> 	retn
  2346                              <1> m17:
  2347                              <1> 	; 14/06/2022
  2348                              <1> 	; ('write_tty' must not return to 'putc' with cf)
  2349 0000152C F8                  <1> 	clc
  2350 0000152D C3                  <1> 	retn
  2351                              <1> 
  2352                              <1> set_ctype:
  2353                              <1> 	; 07/02/2022
  2354                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2355                              <1> 	;
  2356                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2357                              <1> 
  2358                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2359                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2360                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2361                              <1> ;          OR NO CURSOR AT ALL
  2362                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2363                              <1> 
  2364                              <1> ;------------------------------------------------
  2365                              <1> ; SET_CTYPE
  2366                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2367                              <1> ; INPUT
  2368                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2369                              <1> ; OUTPUT	
  2370                              <1> ;	NONE
  2371                              <1> ;------------------------------------------------
  2372                              <1> 
  2373 0000152E B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2374                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2375                              <1> 	;call	m16	; output cx register
  2376                              <1> 	;retn
  2377                              <1> 	; 07/02/2022
  2378 00001530 EBDB                <1> 	jmp	short m16
  2379                              <1> 
  2380                              <1> position:
  2381                              <1> 	; 23/02/2022
  2382                              <1> 	; 02/02/2022
  2383                              <1> 	; 27/06/2015
  2384                              <1> 	; 02/09/2014
  2385                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2386                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2387                              <1> 	;
  2388                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2389                              <1> 	;
  2390                              <1> 	; POSITION
  2391                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2392                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2393                              <1> 	; INPUT
  2394                              <1> 	;	AX = ROW, COLUMN POSITION
  2395                              <1> 	; OUTPUT
  2396                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2397                              <1> 
  2398                              <1> 		; DX = ROW, COLUMN POSITION
  2399                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2400 00001532 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2401 00001534 B050                <1> 	mov	al, 80	; determine bytes to row	
  2402 00001536 F6E6                <1> 	mul	dh	; row value
  2403                              <1> 	;xor	dh, dh	; 0
  2404                              <1> 	;add	ax, dx	; add column value to the result
  2405                              <1> 	; 23/02/2022
  2406 00001538 00D0                <1> 	add	al, dl
  2407 0000153A 80D400              <1> 	adc	ah, 0	
  2408                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2409                              <1> 	; 02/02/2022
  2410 0000153D D1E0                <1> 	shl	eax, 1
  2411                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2412 0000153F C3                  <1> 	retn
  2413                              <1> 
  2414                              <1> find_position:
  2415                              <1> 	; 02/02/2022
  2416                              <1> 	; 27/06/2015
  2417                              <1> 	; 07/09/2014
  2418                              <1> 	; 02/09/2014
  2419                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2420                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2421 00001540 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2422 00001543 89CE                <1> 	mov	esi, ecx
  2423                              <1> 	;shl	si, 1
  2424                              <1> 	; 02/02/2022
  2425 00001545 D1E6                <1> 	shl	esi, 1
  2426 00001547 668B96[B66C0000]    <1> 	mov	dx, [esi+cursor_posn]
  2427 0000154E 7409                <1> 	jz	short p21
  2428                              <1> 	;xor	si, si
  2429                              <1> 	; 02/02/2022
  2430 00001550 31F6                <1> 	xor	esi, esi
  2431                              <1> p20:
  2432                              <1> 	;add	si, [CRT_LEN]
  2433 00001552 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2434 00001557 E2F9                <1> 	loop	p20
  2435                              <1> p21:
  2436 00001559 6621D2              <1> 	and	dx, dx
  2437 0000155C 7407                <1> 	jz	short p22
  2438 0000155E E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2439 00001563 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2440                              <1> p22:	
  2441                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2442                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2443                              <1> 	;add	dx, 6	; point at status port
  2444 00001565 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2445                              <1> 	; cx = 0
  2446 00001569 C3                  <1> 	retn
  2447                              <1> 
  2448                              <1> scroll_up:
  2449                              <1> 	; 02/02/2022 (simplified scroll up)
  2450                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2451                              <1> 	; 16/01/2016
  2452                              <1> 	; 07/09/2014
  2453                              <1> 	; 02/09/2014
  2454                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2455                              <1> 	; 04/04/2014
  2456                              <1> 	; 04/12/2013
  2457                              <1> 	;
  2458                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2459                              <1> 	;
  2460                              <1> 	; SCROLL UP
  2461                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2462                              <1> 	;	ON THE SCREEN
  2463                              <1> 	; INPUT
  2464                              <1> 	;	(AH) = CURRENT CRT MODE
  2465                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2466                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2467                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2468                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2469                              <1> 	;	(DS) = DATA SEGMENT
  2470                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2471                              <1> 	; OUTPUT
  2472                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2473                              <1> 	;
  2474                              <1> 	;	bh = 0  (02/09/2014)
  2475                              <1> 	;
  2476                              <1> 	; ((ah = 3))
  2477                              <1> 	; cl = left upper column
  2478                              <1> 	; ch = left upper row
  2479                              <1> 	; dl = right lower column
  2480                              <1> 	; dh = right lower row
  2481                              <1> 	;
  2482                              <1> 	; al = line count 
  2483                              <1> 	; ah = attribute to be used on blanked line
  2484                              <1> 	; bl = video page number (0 to 7)
  2485                              <1> 	; 
  2486                              <1> 
  2487                              <1> 	; 02/02/2022 'scroll_up' code
  2488                              <1> 	; ------------------------------------------------------
  2489                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2490                              <1> 
  2491                              <1> 	; INPUT:
  2492                              <1> 	;		
  2493                              <1> 	; al = line count 
  2494                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2495                              <1> 	; ah = attribute to be used on blanked line
  2496                              <1> 	; bl = video page number (0 to 7)
  2497                              <1> 
  2498                              <1> 	;cli
  2499 0000156A 31C9                <1> 	xor	ecx, ecx
  2500 0000156C 88C1                <1> 	mov	cl, al ; line count (cl)
  2501 0000156E BE00800B00          <1> 	mov	esi, 0B8000h
  2502 00001573 3A1D[C66C0000]      <1> 	cmp	bl, [active_page]
  2503 00001579 7411                <1> 	je	short n1
  2504 0000157B 20DB                <1> 	and	bl, bl
  2505 0000157D 7422                <1> 	jz	short n3
  2506 0000157F 88DD                <1> 	mov	ch, bl ; video page number
  2507                              <1> n0:
  2508 00001581 6681C6A00F          <1> 	add	si, 25*80*2
  2509 00001586 FECD                <1> 	dec	ch
  2510 00001588 75F7                <1> 	jnz	short n0
  2511 0000158A EB15                <1> 	jmp	short n3
  2512                              <1> n1:
  2513 0000158C 660335[B46C0000]    <1> 	add	si, [CRT_START]
  2514                              <1> 	;
  2515 00001593 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2516                              <1> n2:			 ; wait_display_enable
  2517 00001597 EC                  <1> 	in	al, dx	 ; get port
  2518 00001598 A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2519 0000159A 74FB                <1> 	jz	short n2 ; wait_display_enable
  2520 0000159C B025                <1> 	mov	al, 25h
  2521 0000159E B2D8                <1> 	mov	dl, 0D8h ; address control port
  2522 000015A0 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2523                              <1> n3:
  2524                              <1> 	; cl = line count
  2525                              <1> 	; ah = attribute/color
  2526 000015A1 89F7                <1> 	mov	edi, esi
  2527 000015A3 20C9                <1> 	and	cl, cl
  2528 000015A5 741F                <1> 	jz	short n6
  2529 000015A7 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2530 000015AC 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2531 000015B0 F366A5              <1> 	rep	movsw
  2532 000015B3 B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2533                              <1> n4:
  2534                              <1> 	; ah = character attribute/cocor
  2535 000015B5 B020                <1> 	mov	al, 20h ; fill with blanks
  2536 000015B7 F366AB              <1> 	rep	stosw
  2537                              <1> 
  2538 000015BA 3A1D[C66C0000]      <1> 	cmp	bl, [active_page]
  2539 000015C0 7503                <1> 	jne	short n5
  2540                              <1> 
  2541                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2542 000015C2 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2543                              <1> 	;mov	dx, 03D8h ; always set color card port
  2544 000015C4 EE                  <1> 	out	dx, al
  2545                              <1> n5:
  2546 000015C5 C3                  <1> 	retn
  2547                              <1> n6:
  2548                              <1> 	; clear video page
  2549 000015C6 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2550 000015CA EBE9                <1> 	jmp	short n4
  2551                              <1> 
  2552                              <1> 	; 23/02/2022
  2553                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2554                              <1> 	; ------------------------------------------------------
  2555                              <1> 
  2556                              <1> 	; Test	Line Count
  2557                              <1> 	or	al, al
  2558                              <1> 	jz	short al_set
  2559                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2560                              <1> 	sub	bh, ch
  2561                              <1> 	inc	bh	; adjust difference by 1
  2562                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2563                              <1> 	jne	short al_set ; if not the we're all set
  2564                              <1> 	xor	al, al	; otherwise set al to zero
  2565                              <1> al_set:
  2566                              <1> 	xor	bh, bh	; 0
  2567                              <1> 	;push	ax
  2568                              <1> 	push	eax ; 23/02/2022
  2569                              <1> 	;mov 	esi, [crt_base]
  2570                              <1>         mov     esi, 0B8000h  
  2571                              <1>         cmp     bl, [active_page]
  2572                              <1> 	jne	short n0
  2573                              <1> 	;
  2574                              <1>         mov     ax, [CRT_START]
  2575                              <1>         add     si, ax
  2576                              <1>         jmp     short n1
  2577                              <1> n0:
  2578                              <1>         and     bl, bl
  2579                              <1> 	jz	short n1
  2580                              <1> 	mov	al, bl
  2581                              <1> n0x:
  2582                              <1>         ;add    si, [CRT_LEN]
  2583                              <1>         ;add    esi, 80*25*2 
  2584                              <1>         add     si, 80*25*2
  2585                              <1>         dec	al
  2586                              <1> 	jnz	short n0x
  2587                              <1> n1:	
  2588                              <1>         ; Scroll position
  2589                              <1> 	;push	dx ; 23/02/2022
  2590                              <1> 	mov	dx, cx	; now, upper left position in DX
  2591                              <1> 	call	position
  2592                              <1> 	add	esi, eax
  2593                              <1> 	mov	edi, esi
  2594                              <1> 	;pop	dx	; lower right position in DX
  2595                              <1> 	sub	dx, cx
  2596                              <1> 	inc	dh	; dh = #rows 
  2597                              <1> 	inc	dl	; dl = #cols in block
  2598                              <1> 	;pop	ax	; al = line count, ah = attribute
  2599                              <1> 	pop	eax ; 23/02/2022
  2600                              <1> 	xor	ecx, ecx
  2601                              <1> 	mov	cx, ax
  2602                              <1> 	;mov	ah, [CRT_COLS]
  2603                              <1> 	mov	ah, 80
  2604                              <1> 	mul	ah	; determine offset to from address
  2605                              <1> 	add	ax, ax  ; *2 for attribute byte
  2606                              <1> 	;
  2607                              <1> 	;push	ax	; offset 
  2608                              <1> 	;push	dx
  2609                              <1> 	; 23/02/2022
  2610                              <1> 	push	eax
  2611                              <1> 	push	edx
  2612                              <1> 	;
  2613                              <1> 	; 04/04/2014
  2614                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2615                              <1> n8:                      ; wait_display_enable
  2616                              <1>         in      al, dx   ; get port
  2617                              <1> 	test	al, RVRT ; wait for vertical retrace
  2618                              <1> 	jz	short n8 ; wait_display_enable
  2619                              <1> 	mov	al, 25h
  2620                              <1> 	mov	dl, 0D8h ; address control port
  2621                              <1> 	out	dx, al	; turn off video during vertical retrace
  2622                              <1> 	;pop	dx	; #rows, #cols
  2623                              <1>        	;pop	ax	; offset
  2624                              <1> 	; 23/02/2022
  2625                              <1> 	pop	edx
  2626                              <1> 	pop	eax
  2627                              <1> 	xchg	ax, cx	; 
  2628                              <1> 	; ecx = offset, al = line count, ah = attribute
  2629                              <1> ;n9:
  2630                              <1> 	or	al, al
  2631                              <1>         jz      short n3 
  2632                              <1>         add     esi, ecx ; from address for scroll
  2633                              <1> 	mov	bh, dh  ; #rows in block
  2634                              <1> 	sub	bh, al	; #rows to be moved
  2635                              <1> n2:
  2636                              <1> 	; Move rows
  2637                              <1> 	mov	cl, dl	; get # of cols to move
  2638                              <1> 	push	esi
  2639                              <1> 	push	edi	; save start address
  2640                              <1> n10:
  2641                              <1> 	movsw		; move that line on screen
  2642                              <1> 	dec	cl
  2643                              <1>         jnz     short n10
  2644                              <1> 	pop	edi
  2645                              <1> 	pop	esi	; recover addresses
  2646                              <1>         ;mov    cl, [CRT_COLS] 
  2647                              <1> 	;add	cl, cl
  2648                              <1>         ;mov    ecx, 80*2
  2649                              <1>         mov     cx, 80*2
  2650                              <1>         add     esi, ecx  ; next line
  2651                              <1>         add     edi, ecx
  2652                              <1> 	dec	bh	 ; count of lines to move
  2653                              <1> 	jnz	short n2 ; row loop
  2654                              <1> 	; bh = 0
  2655                              <1> 	mov	dh, al	 ; #rows	
  2656                              <1> n3:
  2657                              <1> 	; attribute in ah
  2658                              <1> 	mov	al, ' '	 ; fill with blanks
  2659                              <1> n3x:
  2660                              <1> 	; Clear rows
  2661                              <1>                 ; dh =  #rows
  2662                              <1>         mov	cl, dl	; get # of cols to clear
  2663                              <1>         push    edi     ; save address
  2664                              <1> n11:
  2665                              <1>         stosw           ; store fill character
  2666                              <1> 	dec	cl
  2667                              <1>         jnz     short n11
  2668                              <1>         pop     edi     ; recover address
  2669                              <1> 	;mov	cl, [CRT_COLS]
  2670                              <1> 	;add	cl, cl
  2671                              <1>         ;mov    ecx, 80*2
  2672                              <1>         mov	cl, 80*2
  2673                              <1>         add     edi, ecx
  2674                              <1> 	dec	dh
  2675                              <1> 	jnz	short n3x ; 16/01/2016
  2676                              <1> 	;
  2677                              <1> 	cmp	bl, [active_page]
  2678                              <1> 	jne	short n6
  2679                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2680                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2681                              <1> 	mov	dx, 03D8h ; always set color card port
  2682                              <1> 	out	dx, al
  2683                              <1> n6:
  2684                              <1> 	retn
  2685                              <1> 
  2686                              <1> %endif
  2687                              <1> 
  2688                              <1> write_c_current:
  2689                              <1> 	; 02/02/2022
  2690                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2691                              <1> 	; 18/01/2014
  2692                              <1> 	; 04/12/2013
  2693                              <1> 	;
  2694                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2695                              <1> 	;
  2696                              <1> 	; WRITE_C_CURRENT
  2697                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2698                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2699                              <1> 	; INPUT	
  2700                              <1> 	;	(AH) = CURRENT CRT MODE
  2701                              <1> 	;	(BH) = DISPLAY PAGE
  2702                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2703                              <1> 	;	(AL) = CHAR TO WRITE
  2704                              <1> 	;	(DS) = DATA SEGMENT
  2705                              <1> 	;	(ES) = REGEN SEGMENT
  2706                              <1> 	; OUTPUT
  2707                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2708                              <1> 
  2709 000015CC FA                  <1> 	cli		
  2710                              <1> 	; bl = video page
  2711                              <1> 	; al = character
  2712                              <1> 	; ah = color/attribute
  2713                              <1> 	;push	dx
  2714                              <1> 	;push	ax	; save character & attribute/color
  2715                              <1> 	; 02/02/2022
  2716 000015CD 52                  <1> 	push	edx
  2717 000015CE 50                  <1> 	push	eax
  2718 000015CF E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2719                              <1> 	; esi = regen location
  2720                              <1> 	; dx = status port
  2721                              <1> 	;
  2722                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2723                              <1> 	;
  2724                              <1> p41:			; wait for horizontal retrace is low or vertical
  2725 000015D4 FB                  <1> 	sti		; enable interrupts first
  2726 000015D5 3A1D[C66C0000]      <1>         cmp     bl, [active_page]
  2727 000015DB 7510                <1> 	jne	short p44 
  2728 000015DD FA                  <1> 	cli 		; block interrupts for single loop
  2729 000015DE EC                  <1> 	in	al, dx	; get status from the adapter
  2730 000015DF A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2731 000015E1 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2732 000015E3 A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2733 000015E5 75ED                <1> 	jnz	short p41 ; wait until it is
  2734                              <1> p42:			; wait for either retrace high
  2735 000015E7 EC                  <1> 	in	al, dx	; get status again
  2736 000015E8 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2737 000015EA 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2738                              <1> p43:	
  2739 000015EC FB                  <1> 	sti
  2740                              <1> p44:
  2741                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2742                              <1> 	; 02/02/2022
  2743 000015ED 58                  <1> 	pop	eax
  2744 000015EE 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2745                              <1> 			; Retro UNIX 386 v1 feature only!
  2746 000015F4 668906              <1> 	mov	[esi], ax
  2747                              <1> 	;pop	dx
  2748                              <1> 	; 02/02/2022
  2749 000015F7 5A                  <1> 	pop	edx
  2750 000015F8 C3                  <1> 	retn
  2751                              <1> 
  2752                              <1> %if 0	; 02/02/2022
  2753                              <1> 
  2754                              <1> set_mode:
  2755                              <1> 	; 02/02/2022
  2756                              <1> 	; 16/01/2016
  2757                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2758                              <1> 	;
  2759                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2760                              <1> 
  2761                              <1> ;------------------------------------------------------
  2762                              <1> ; SET MODE					      :
  2763                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2764                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2765                              <1> ; INPUT						      :
  2766                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2767                              <1> ; OUTPUT					      :
  2768                              <1> ;	NONE					      :
  2769                              <1> ;------------------------------------------------------
  2770                              <1> 
  2771                              <1> 	push	edi ; 16/01/2016
  2772                              <1> 	push	ebx
  2773                              <1> 	push	edx
  2774                              <1> 	push	ecx ; 16/01/2016
  2775                              <1>         push    eax
  2776                              <1> 
  2777                              <1> 	;mov	dx, 03D4h 	; address or color card
  2778                              <1> 	mov	al, 3
  2779                              <1> ;M8:
  2780                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2781                              <1> 	mov	al, 29h
  2782                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2783                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2784                              <1> 	;push	dx  		; save port value
  2785                              <1> 	;add	dx, 4		; point to control register
  2786                              <1> 	mov	dx, 3D8h
  2787                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2788                              <1> 	;pop	dx
  2789                              <1> ;M9:
  2790                              <1> 	mov	ebx, video_params ; initialization table
  2791                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2792                              <1> 	;xchg 	ah, al
  2793                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2794                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2795                              <1> 	
  2796                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2797                              <1> 	; 02/02/2022
  2798                              <1> 	; dx = 3D8h
  2799                              <1> 	xor	ecx, ecx
  2800                              <1> 	mov	cl, 16
  2801                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2802                              <1> M10:			;  initialization loop
  2803                              <1> 	mov	al, ah 	; get 6845 register number
  2804                              <1> 	out	dx, al
  2805                              <1> 	;inc	dx      ; point to data port
  2806                              <1> 	; 02/02/2022
  2807                              <1> 	inc	dl ; 3D9h
  2808                              <1> 	inc	ah	; next register value
  2809                              <1> 	mov	al, [ebx] ; get table value
  2810                              <1> 	out	dx, al	; out to chip
  2811                              <1> 	inc	ebx	; next in table
  2812                              <1> 	;dec	dx	; back to pointer register
  2813                              <1> 	; 02/02/2022
  2814                              <1> 	dec	dl ; 3D8h
  2815                              <1> 	loop	M10	; do the whole table
  2816                              <1> 	
  2817                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2818                              <1> 	;xor	ax, ax  
  2819                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2820                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2821                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2822                              <1> 	; black background, light gray characeter color, space character
  2823                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2824                              <1> ;M13:			  ; clear buffer
  2825                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2826                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2827                              <1> 
  2828                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2829                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2830                              <1> 			 ; prepare to output to video enable port
  2831                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2832                              <1> 	; 02/02/2022
  2833                              <1> 	;mov	dx, 3D8h
  2834                              <1> 	; 
  2835                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2836                              <1> 	mov	al, 29h
  2837                              <1> 	out	dx, al	 ; set video enable port
  2838                              <1> 
  2839                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2840                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2841                              <1> 	;
  2842                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2843                              <1> 	;
  2844                              <1> ;-----	SET CURSOR POSITIONS
  2845                              <1> 	;push	edi
  2846                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2847                              <1> 	mov	edi, cursor_posn
  2848                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2849                              <1> 	xor	eax, eax
  2850                              <1> 	rep 	stosd	; fill with zeroes
  2851                              <1> 	;pop	edi
  2852                              <1> 
  2853                              <1> ;-----	SET UP OVERSCAN REGISTER
  2854                              <1> 	inc	dx	; set overscan port to a default
  2855                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2856                              <1> ;M14:
  2857                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2858                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2859                              <1> 
  2860                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2861                              <1> 	;
  2862                              <1> 	pop	eax
  2863                              <1> 	pop	ecx ; 16/01/2016
  2864                              <1> 	pop	edx
  2865                              <1> 	pop	ebx
  2866                              <1> 	pop	edi ; 16/01/2016
  2867                              <1> 	retn
  2868                              <1> 
  2869                              <1> %endif
  2870                              <1> 	
  2871                              <1> tty_sw:
  2872                              <1> 	; 02/02/2022
  2873                              <1> 	; 30/06/2015
  2874                              <1> 	; 27/06/2015 
  2875                              <1> 	; 07/09/2014
  2876                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2877                              <1> 	;
  2878                              <1> 	; (Modified registers : EAX)
  2879                              <1> 	;
  2880                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2881                              <1> 	;
  2882                              <1> ;act_disp_page:
  2883                              <1> 	; 30/06/2015
  2884                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2885                              <1> 	; 10/12/2013
  2886                              <1> 	; 04/12/2013
  2887                              <1> 	;
  2888                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2889                              <1> 	;
  2890                              <1> 	; ACT_DISP_PAGE
  2891                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2892                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2893                              <1> 	; INPUT
  2894                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2895                              <1> 	; OUTPUT
  2896                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2897                              <1> 
  2898                              <1> 	;cli
  2899                              <1> 
  2900 000015F9 53                  <1> 	push	ebx
  2901                              <1> 	;push	cx
  2902                              <1> 	;push	dx
  2903                              <1> 	; 02/02/2022
  2904 000015FA 51                  <1> 	push	ecx
  2905 000015FB 52                  <1> 	push	edx
  2906                              <1> 	;
  2907 000015FC A2[C66C0000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2908                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2909                              <1> 	;mov	cx, 25*80*2
  2910                              <1> 	; 02/02/2022
  2911 00001601 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2912                              <1> 	; 27/06/2015
  2913 00001606 0FB6D8              <1> 	movzx	ebx, al
  2914                              <1> 	; 02/02/2022
  2915 00001609 89D8                <1> 	mov	eax, ebx
  2916                              <1> 	;
  2917                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2918                              <1> 	;mul 	cx	; display page times regen length
  2919                              <1> 	; 02/02/2022
  2920 0000160B F7E1                <1> 	mul	ecx	
  2921                              <1> 	; 10/12/2013
  2922 0000160D 66A3[B46C0000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2923                              <1> 	;mov	cx, ax	; start address to cx
  2924                              <1> 	; 02/02/2022
  2925 00001613 89C1                <1> 	mov	ecx, eax
  2926                              <1> 	;sar	cx, 1
  2927                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2928                              <1> 	; 02/02/2022
  2929 00001615 D1E9                <1> 	shr	ecx, 1
  2930 00001617 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2931 00001619 E8EFFEFFFF          <1> 	call	m16
  2932                              <1> 	;sal	bx, 1
  2933                              <1> 	; 01/09/2014
  2934 0000161E D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2935 00001620 81C3[B66C0000]      <1> 	add	ebx, cursor_posn
  2936 00001626 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2937 00001629 E8CDFEFFFF          <1> 	call	m18
  2938                              <1> 	;
  2939                              <1> 	;pop	dx
  2940                              <1> 	;pop	cx
  2941                              <1> 	; 02/02/2022
  2942 0000162E 5A                  <1> 	pop	edx
  2943 0000162F 59                  <1> 	pop	ecx
  2944 00001630 5B                  <1> 	pop	ebx
  2945                              <1> 	;
  2946                              <1> 	;sti
  2947                              <1> 	;
  2948 00001631 C3                  <1> 	retn
  2949                              <1> 
  2950                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2951                              <1> 
  2952                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1832                                  
  1833                                  setup_rtc_int:
  1834                                  ; source: http://wiki.osdev.org/RTC
  1835 00001632 FA                      	cli		; disable interrupts
  1836                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1837                                  	; in order to change this ...
  1838                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1839                                  	; (rate must be above 2 and not over 15)
  1840                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1841 00001633 B08A                    	mov	al, 8Ah 
  1842 00001635 E670                    	out	70h, al ; set index to register A, disable NMI
  1843 00001637 90                      	nop
  1844 00001638 E471                    	in	al, 71h ; get initial value of register A
  1845 0000163A 88C4                    	mov 	ah, al
  1846 0000163C 80E4F0                  	and	ah, 0F0h
  1847 0000163F B08A                    	mov	al, 8Ah 
  1848 00001641 E670                    	out	70h, al ; reset index to register A
  1849 00001643 88E0                    	mov	al, ah
  1850 00001645 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1851 00001647 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1852                                  	; enable RTC interrupt
  1853 00001649 B08B                    	mov	al, 8Bh ;
  1854 0000164B E670                    	out	70h, al ; select register B and disable NMI
  1855 0000164D 90                      	nop
  1856 0000164E E471                    	in	al, 71h ; read the current value of register B
  1857 00001650 88C4                    	mov	ah, al  ;
  1858 00001652 B08B                    	mov 	al, 8Bh ;
  1859 00001654 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1860 00001656 88E0                    	mov	al, ah  ;
  1861 00001658 0C40                    	or	al, 40h ;
  1862 0000165A E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1863 0000165C FB                      	sti
  1864 0000165D C3                      	retn
  1865                                  
  1866                                  ; Write memory information
  1867                                  ; Temporary Code
  1868                                  ; 06/11/2014
  1869                                  ; 14/08/2015 
  1870                                  memory_info:	
  1871 0000165E A1[9C6C0000]            	mov	eax, [memory_size] ; in pages
  1872 00001663 50                      	push	eax
  1873 00001664 C1E00C                  	shl	eax, 12		   ; in bytes
  1874 00001667 BB0A000000              	mov	ebx, 10
  1875 0000166C 89D9                    	mov	ecx, ebx	   ; 10
  1876 0000166E BE[FF680000]            	mov	esi, mem_total_b_str	
  1877 00001673 E8B2000000              	call	bintdstr
  1878 00001678 58                      	pop	eax
  1879 00001679 B107                    	mov	cl, 7
  1880 0000167B BE[23690000]            	mov	esi, mem_total_p_str
  1881 00001680 E8A5000000              	call	bintdstr	
  1882                                  	; 14/08/2015
  1883 00001685 E8BD000000              	call	calc_free_mem
  1884                                  	; edx = calculated free pages
  1885                                  	; ecx = 0
  1886 0000168A A1[A06C0000]            	mov 	eax, [free_pages]
  1887 0000168F 39D0                    	cmp	eax, edx ; calculated free mem value 
  1888                                  		; and initial free mem value are same or not?
  1889 00001691 751D                    	jne 	short pmim ; print mem info with '?' if not
  1890 00001693 52                      	push 	edx ; free memory in pages	
  1891                                  	;mov 	eax, edx
  1892 00001694 C1E00C                  	shl	eax, 12 ; convert page count
  1893                                  			; to byte count
  1894 00001697 B10A                    	mov	cl, 10
  1895 00001699 BE[43690000]            	mov	esi, free_mem_b_str
  1896 0000169E E887000000              	call	bintdstr
  1897 000016A3 58                      	pop	eax
  1898 000016A4 B107                    	mov	cl, 7
  1899 000016A6 BE[67690000]            	mov	esi, free_mem_p_str
  1900 000016AB E87A000000              	call	bintdstr
  1901                                  pmim:
  1902 000016B0 BE[ED680000]            	mov	esi, msg_memory_info
  1903                                  pmim_nb:	
  1904 000016B5 AC                      	lodsb
  1905 000016B6 08C0                    	or	al, al
  1906 000016B8 740D                    	jz	short pmim_ok
  1907 000016BA 56                      	push	esi
  1908 000016BB 31DB                    	xor	ebx, ebx ; 0
  1909                                  			; Video page 0 (bl=0)
  1910 000016BD B407                    	mov	ah, 07h ; Black background, 
  1911                                  			; light gray forecolor
  1912 000016BF E816FDFFFF              	call	write_tty
  1913 000016C4 5E                      	pop	esi
  1914 000016C5 EBEE                    	jmp	short pmim_nb
  1915                                  pmim_ok:
  1916 000016C7 C3                      	retn
  1917                                  
  1918                                  ; Convert binary number to hexadecimal string
  1919                                  ; 10/05/2015  
  1920                                  ; dsectpm.s (28/02/2015)
  1921                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1922                                  ; 01/12/2014
  1923                                  ; 25/11/2014
  1924                                  ;
  1925                                  bytetohex:
  1926                                  	; INPUT ->
  1927                                  	; 	AL = byte (binary number)
  1928                                  	; OUTPUT ->
  1929                                  	;	AX = hexadecimal string
  1930                                  	;
  1931 000016C8 53                      	push	ebx
  1932 000016C9 31DB                    	xor	ebx, ebx
  1933 000016CB 88C3                    	mov	bl, al
  1934 000016CD C0EB04                  	shr	bl, 4
  1935 000016D0 8A9B[1A170000]          	mov	bl, [ebx+hexchrs] 	 	
  1936 000016D6 86D8                    	xchg	bl, al
  1937 000016D8 80E30F                  	and	bl, 0Fh
  1938 000016DB 8AA3[1A170000]          	mov	ah, [ebx+hexchrs] 
  1939 000016E1 5B                      	pop	ebx	
  1940 000016E2 C3                      	retn
  1941                                  
  1942                                  wordtohex:
  1943                                  	; INPUT ->
  1944                                  	; 	AX = word (binary number)
  1945                                  	; OUTPUT ->
  1946                                  	;	EAX = hexadecimal string
  1947                                  	;
  1948 000016E3 53                      	push	ebx
  1949 000016E4 31DB                    	xor	ebx, ebx
  1950 000016E6 86E0                    	xchg	ah, al
  1951 000016E8 6650                    	push	ax
  1952 000016EA 88E3                    	mov	bl, ah
  1953 000016EC C0EB04                  	shr	bl, 4
  1954 000016EF 8A83[1A170000]          	mov	al, [ebx+hexchrs] 	 	
  1955 000016F5 88E3                    	mov	bl, ah
  1956 000016F7 80E30F                  	and	bl, 0Fh
  1957 000016FA 8AA3[1A170000]          	mov	ah, [ebx+hexchrs]
  1958 00001700 C1E010                  	shl	eax, 16
  1959 00001703 6658                    	pop	ax
  1960 00001705 5B                      	pop	ebx
  1961 00001706 EBC0                    	jmp	short bytetohex
  1962                                  	;mov	bl, al
  1963                                  	;shr	bl, 4
  1964                                  	;mov	bl, [ebx+hexchrs] 	 	
  1965                                  	;xchg	bl, al	 	
  1966                                  	;and	bl, 0Fh
  1967                                  	;mov	ah, [ebx+hexchrs] 
  1968                                  	;pop	ebx	
  1969                                  	;retn
  1970                                  
  1971                                  dwordtohex:
  1972                                  	; INPUT ->
  1973                                  	; 	EAX = dword (binary number)
  1974                                  	; OUTPUT ->
  1975                                  	;	EDX:EAX = hexadecimal string
  1976                                  	;
  1977 00001708 50                      	push	eax
  1978 00001709 C1E810                  	shr	eax, 16
  1979 0000170C E8D2FFFFFF              	call	wordtohex
  1980 00001711 89C2                    	mov	edx, eax
  1981 00001713 58                      	pop	eax
  1982 00001714 E8CAFFFFFF              	call	wordtohex
  1983 00001719 C3                      	retn
  1984                                  
  1985                                  ; 10/05/2015
  1986                                  hex_digits:
  1987                                  hexchrs:
  1988 0000171A 303132333435363738-     	db '0123456789ABCDEF'
  1988 00001723 39414243444546     
  1989                                  
  1990                                  ; Convert binary number to decimal/numeric string
  1991                                  ; 06/11/2014
  1992                                  ; Temporary Code
  1993                                  ;
  1994                                  
  1995                                  bintdstr:
  1996                                  	; EAX = binary number
  1997                                  	; ESI = decimal/numeric string address
  1998                                  	; EBX = divisor (10)
  1999                                  	; ECX = string length (<=10)
  2000 0000172A 01CE                    	add	esi, ecx
  2001                                  btdstr0:
  2002 0000172C 4E                      	dec	esi
  2003 0000172D 31D2                    	xor	edx, edx
  2004 0000172F F7F3                    	div	ebx
  2005 00001731 80C230                  	add	dl, 30h
  2006 00001734 8816                    	mov	[esi], dl
  2007 00001736 FEC9                    	dec	cl
  2008 00001738 740C                    	jz	btdstr2
  2009 0000173A 09C0                    	or	eax, eax
  2010 0000173C 75EE                    	jnz	short btdstr0
  2011                                  btdstr1:
  2012 0000173E 4E                      	dec	esi
  2013 0000173F C60620                          mov     byte [esi], 20h ; blank space
  2014 00001742 FEC9                    	dec	cl
  2015 00001744 75F8                    	jnz	short btdstr1
  2016                                  btdstr2:
  2017 00001746 C3                      	retn
  2018                                  
  2019                                  ; Calculate free memory pages on M.A.T.
  2020                                  ; 06/11/2014
  2021                                  ; Temporary Code
  2022                                  ;
  2023                                  
  2024                                  calc_free_mem:
  2025 00001747 31D2                    	xor	edx, edx
  2026                                  	;xor	ecx, ecx
  2027 00001749 668B0D[B06C0000]        	mov	cx, [mat_size] ; in pages
  2028 00001750 C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2029 00001753 BE00001000              	mov	esi, MEM_ALLOC_TBL
  2030                                  cfm0:
  2031 00001758 AD                      	lodsd
  2032 00001759 51                      	push	ecx
  2033 0000175A B920000000              	mov	ecx, 32
  2034                                  cfm1:
  2035 0000175F D1E8                    	shr	eax, 1
  2036 00001761 7301                    	jnc	short cfm2
  2037 00001763 42                      	inc	edx
  2038                                  cfm2:
  2039 00001764 E2F9                    	loop	cfm1
  2040 00001766 59                      	pop	ecx
  2041 00001767 E2EF                    	loop	cfm0
  2042 00001769 C3                      	retn
  2043                                  
  2044                                  %include 'diskio.inc'  ; 07/03/2015
  2045                              <1> ; Retro UNIX 386 v1 Kernel - DISKIO.INC
  2046                              <1> ; Last Modification: 24/12/2021
  2047                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2048                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2049                              <1> 
  2050                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2051                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2052                              <1> 
  2053                              <1> ; 06/02/2015
  2054                              <1> diskette_io:
  2055 0000176A 9C                  <1> 	pushfd
  2056 0000176B 0E                  <1> 	push 	cs
  2057 0000176C E809000000          <1> 	call 	DISKETTE_IO_1
  2058 00001771 C3                  <1> 	retn
  2059                              <1> 	
  2060                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2061                              <1> ;//////////////////////////////////////////////////////
  2062                              <1> 
  2063                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2064                              <1> 
  2065                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2066                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2067                              <1> ; 20/02/2015
  2068                              <1> ; 06/02/2015 (Retro UNIX 386 v1, unix386.s)
  2069                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2070                              <1> ;
  2071                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2072                              <1> ;
  2073                              <1> ; ADISK.EQU
  2074                              <1> 
  2075                              <1> ;----- Wait control constants 
  2076                              <1> 
  2077                              <1> ;amount of time to wait while RESET is active.
  2078                              <1> 
  2079                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2080                              <1> 					;at 250 KBS xfer rate.
  2081                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2082                              <1> 
  2083                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2084                              <1> 					;status register to become valid
  2085                              <1> 					;before re-reading.
  2086                              <1> 
  2087                              <1> ;After sending a byte to NEC, status register may remain
  2088                              <1> ;incorrectly set for 24 us.
  2089                              <1> 
  2090                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2091                              <1> 					;RQM low.
  2092                              <1> 
  2093                              <1> ; COMMON.MAC
  2094                              <1> ;
  2095                              <1> ;	Timing macros
  2096                              <1> ;
  2097                              <1> 
  2098                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2099                              <1> 		jmp short $+2
  2100                              <1> %endmacro		
  2101                              <1> 
  2102                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2103                              <1> 		jmp short $+2
  2104                              <1> 		jmp short $+2
  2105                              <1> %endmacro
  2106                              <1> 
  2107                              <1> %macro		NEWIODELAY 0
  2108                              <1> 		out	0EBh,al
  2109                              <1> %endmacro 
  2110                              <1> 
  2111                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2112                              <1> ;;; WAIT_FOR_MEM
  2113                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2114                              <1> ;WAIT_FDU_INT_HI	equ	1
  2115                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2116                              <1> ;;; WAIT_FOR_PORT
  2117                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2118                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2119                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2120                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2121                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2122                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2123                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2124                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2125                              <1> ;;; WAIT_REFRESH
  2126                              <1> ;amount of time to wait for head settle, per unit in parameter
  2127                              <1> ;table = 1 ms.
  2128                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2129                              <1> 
  2130                              <1> 
  2131                              <1> ; //////////////// DISKETTE I/O ////////////////
  2132                              <1> 
  2133                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2134                              <1> 
  2135                              <1> ;----------------------------------------
  2136                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2137                              <1> ;----------------------------------------
  2138                              <1> 
  2139                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2140                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2141                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2142                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2143                              <1> 
  2144                              <1> ;----------------------------------------
  2145                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2146                              <1> ;-------------------------------------------------------------------------------
  2147                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2148                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2149                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2150                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2151                              <1> 
  2152                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2153                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2154                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2155                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2156                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2157                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2158                              <1> 
  2159                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2160                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2161                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2162                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2163                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2164                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2165                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2166                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2167                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2168                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2169                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2170                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2171                              <1> 
  2172                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2173                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2174                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2175                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2176                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2177                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2178                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2179                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2180                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2181                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2182                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2183                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2184                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2185                              <1> 
  2186                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2187                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2188                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2189                              <1> 
  2190                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2191                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2192                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2193                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2194                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2195                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2196                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2197                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2198                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2199                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2200                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2201                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2202                              <1> 
  2203                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2204                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2205                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2206                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2207                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2208                              <1> 
  2209                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2210                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2211                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2212                              <1> INTA01		EQU	021H		; 8259 PORT
  2213                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2214                              <1> INTB01		EQU	0A1H		;
  2215                              <1> 
  2216                              <1> ;-------------------------------------------------------------------------------
  2217                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2218                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2219                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2220                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2221                              <1> ;-------------------------------------------------------------------------------
  2222                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2223                              <1> 
  2224                              <1> ;-------------------------------------------------------------------------------
  2225                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2226                              <1> 
  2227                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2228                              <1> ; (unix386.s <-- dsectrm2.s)
  2229                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2230                              <1> 
  2231                              <1> ; 10/12/2014
  2232                              <1> ;
  2233                              <1> ;int40h:
  2234                              <1> ;	pushf
  2235                              <1> ;	push 	cs
  2236                              <1> ;	;cli
  2237                              <1> ;	call 	DISKETTE_IO_1
  2238                              <1> ;	retn
  2239                              <1> 
  2240                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2241                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2242                              <1> ;
  2243                              <1> 
  2244                              <1> ;-- INT13H ---------------------------------------------------------------------
  2245                              <1> ; DISKETTE I/O
  2246                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2247                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2248                              <1> ; INPUT
  2249                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2250                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2251                              <1> ;		ON ALL DRIVES
  2252                              <1> ;------------------------------------------------------------------------------- 
  2253                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2254                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2255                              <1> ;-------------------------------------------------------------------------------
  2256                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2257                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2258                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2259                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2260                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2261                              <1> ;		320/360	320/360	    0-39
  2262                              <1> ;		320/360	1.2M	    0-39
  2263                              <1> ;		1.2M	1.2M	    0-79
  2264                              <1> ;		720K	720K	    0-79
  2265                              <1> ;		1.44M	1.44M	    0-79	
  2266                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2267                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2268                              <1> ;		320/360	320/360	     1-8/9
  2269                              <1> ;		320/360	1.2M	     1-8/9
  2270                              <1> ;		1.2M	1.2M	     1-15
  2271                              <1> ;		720K	720K	     1-9
  2272                              <1> ;		1.44M	1.44M	     1-18		
  2273                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2274                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2275                              <1> ;		320/360	320/360	        8/9
  2276                              <1> ;		320/360	1.2M	        8/9
  2277                              <1> ;		1.2M	1.2M		15
  2278                              <1> ;		720K	720K		9
  2279                              <1> ;		1.44M	1.44M		18
  2280                              <1> ;
  2281                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2282                              <1> ;
  2283                              <1> ;-------------------------------------------------------------------------------
  2284                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2285                              <1> ;-------------------------------------------------------------------------------
  2286                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2287                              <1> ;-------------------------------------------------------------------------------
  2288                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2289                              <1> ;-------------------------------------------------------------------------------
  2290                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2291                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2292                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2293                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2294                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2295                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2296                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2297                              <1> ;		READ/WRITE ACCESS.
  2298                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2299                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2300                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2301                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2302                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2303                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2304                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2305                              <1> ;
  2306                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2307                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2308                              <1> ;		---------------------------------------------
  2309                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2310                              <1> ;		---------------------------------------------
  2311                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2312                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2313                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2314                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2315                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2316                              <1> ;		---------------------------------------------
  2317                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2318                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2319                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2320                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2321                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2322                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2323                              <1> ;-------------------------------------------------------------------------------
  2324                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2325                              <1> ;	REGISTERS
  2326                              <1> ;	  INPUT
  2327                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2328                              <1> ;	  OUTPUT
  2329                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2330                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2331                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2332                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2333                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2334                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2335                              <1> ;	    (BH) - 0
  2336                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2337                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2338                              <1> ;	    (AX) - 0
  2339                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2340                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2341                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2342                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2343                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2344                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2345                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2346                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2347                              <1> ;-------------------------------------------------------------------------------
  2348                              <1> ;	(AH)= 15H  READ DASD TYPE
  2349                              <1> ;	OUTPUT REGISTERS
  2350                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2351                              <1> ;		00 - DRIVE NOT PRESENT	
  2352                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2353                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2354                              <1> ;		03 - RESERVED (FIXED DISK)
  2355                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2356                              <1> ;-------------------------------------------------------------------------------
  2357                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2358                              <1> ;	OUTPUT REGISTERS
  2359                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2360                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2361                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2362                              <1> ;-------------------------------------------------------------------------------
  2363                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2364                              <1> ;	INPUT REGISTERS
  2365                              <1> ;	(AL) -	00 - NOT USED	
  2366                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2367                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2368                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2369                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2370                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2371                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2372                              <1> ;-------------------------------------------------------------------------------
  2373                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2374                              <1> ;	INPUT REGISTERS
  2375                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2376                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2377                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2378                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2379                              <1> ;	OUTPUT REGISTERS:
  2380                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2381                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2382                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2383                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2384                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2385                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2386                              <1> ;-------------------------------------------------------------------------------
  2387                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2388                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2389                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2390                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2391                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2392                              <1> ;		CHANGE ERROR CODE
  2393                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2394                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2395                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2396                              <1> ;
  2397                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2398                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2399                              <1> ;-------------------------------------------------------------------------------
  2400                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2401                              <1> ;	AH = STATUS OF OPERATION
  2402                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2403                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2404                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2405                              <1> ;		TYPE AH=(15)).
  2406                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2407                              <1> ;	FOR READ/WRITE/VERIFY
  2408                              <1> ;		DS,BX,DX,CX PRESERVED
  2409                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2410                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2411                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2412                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2413                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2414                              <1> ;-------------------------------------------------------------------------------
  2415                              <1> ;
  2416                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2417                              <1> ;
  2418                              <1> ;   -----------------------------------------------------------------
  2419                              <1> ;   |       |       |       |       |       |       |       |       |
  2420                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2421                              <1> ;   |       |       |       |       |       |       |       |       |
  2422                              <1> ;   -----------------------------------------------------------------
  2423                              <1> ;	|	|	|	|	|	|	|	|
  2424                              <1> ;	|	|	|	|	|	-----------------
  2425                              <1> ;	|	|	|	|	|		|
  2426                              <1> ;	|	|	|	|    RESERVED		|
  2427                              <1> ;	|	|	|	|		  PRESENT STATE
  2428                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2429                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2430                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2431                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2432                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2433                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2434                              <1> ;	|	|	|	|	110: RESERVED
  2435                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2436                              <1> ;	|	|	|	|
  2437                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2438                              <1> ;	|	|	|
  2439                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2440                              <1> ;	|	|			DRIVE)
  2441                              <1> ;	|	|
  2442                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2443                              <1> ;
  2444                              <1> ;						00: 500 KBS
  2445                              <1> ;						01: 300 KBS
  2446                              <1> ;						10: 250 KBS
  2447                              <1> ;						11: RESERVED
  2448                              <1> ;
  2449                              <1> ;
  2450                              <1> ;-------------------------------------------------------------------------------
  2451                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2452                              <1> ;-------------------------------------------------------------------------------
  2453                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2454                              <1> ;-------------------------------------------------------------------------------
  2455                              <1> 
  2456                              <1> struc MD
  2457 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2458 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2459 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2460 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2461 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2462 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2463 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2464 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2465 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2466 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2467 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2468 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2469 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2470                              <1> endstruc
  2471                              <1> 
  2472                              <1> BIT7OFF	EQU	7FH
  2473                              <1> BIT7ON	EQU	80H
  2474                              <1> 
  2475                              <1> ;;int13h: ; 16/02/2015
  2476                              <1> ;; 16/02/2015 - 21/02/2015
  2477                              <1> int40h:
  2478 00001772 9C                  <1> 	pushfd
  2479 00001773 0E                  <1> 	push 	cs
  2480 00001774 E801000000          <1> 	call 	DISKETTE_IO_1
  2481 00001779 C3                  <1> 	retn	
  2482                              <1> 
  2483                              <1> DISKETTE_IO_1:
  2484                              <1> 
  2485 0000177A FB                  <1> 	STI				; INTERRUPTS BACK ON
  2486 0000177B 55                  <1> 	PUSH	eBP			; USER REGISTER
  2487 0000177C 57                  <1> 	PUSH	eDI			; USER REGISTER
  2488 0000177D 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2489 0000177E 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2490 0000177F 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2491 00001780 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2492                              <1> 					; [BP]   = SECTOR #
  2493                              <1> 					; [BP+1] = TRACK #
  2494                              <1> 					; [BP+2] = BUFFER OFFSET
  2495                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2496                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2497                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2498                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2499                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2500                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2501                              <1> 					; BH/[BP+3] = 0
  2502                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2503                              <1> 					; DH/[BP+5] = MAX HEAD #
  2504                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2505 00001782 06                  <1> 	push	es ; 06/02/2015	
  2506 00001783 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2507 00001784 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2508                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2509                              <1> 	;mov	cx, cs
  2510                              <1> 	;mov	ds, cx
  2511 00001785 66B91000            <1> 	mov	cx, KDATA
  2512 00001789 8ED9                <1>         mov     ds, cx
  2513 0000178B 8EC1                <1>         mov     es, cx
  2514                              <1> 
  2515                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2516 0000178D 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2517 00001790 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2518 00001792 B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2519                              <1> OK_FUNC:
  2520 00001794 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2521 00001797 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2522 00001799 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2523 0000179C 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2524 0000179E 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2525 000017A1 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2526 000017A3 B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2527                              <1> OK_DRV:
  2528 000017A5 31C9                <1> 	xor	ecx, ecx
  2529                              <1> 	;mov	esi, ecx ; 08/02/2015
  2530                              <1> 	; 24/12/2021
  2531 000017A7 89CE                <1> 	mov	esi, ecx
  2532 000017A9 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2533 000017AB 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2534                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2535                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2536 000017AD C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2537 000017B0 BB[E8170000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2538 000017B5 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2539 000017B7 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2540 000017B9 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2541 000017BB 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2542 000017BE 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2543                              <1> 	;
  2544                              <1> 	; 11/12/2014
  2545 000017C1 8815[81670000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2546                              <1> 	;
  2547 000017C7 8A25[1C6D0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2548 000017CD C605[1C6D0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2549                              <1> 
  2550                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2551                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2552                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2553                              <1> ;
  2554                              <1> ;		DI	: DRIVE #
  2555                              <1> ;		SI-HI	: HEAD #
  2556                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2557                              <1> ;		ES	: BUFFER SEGMENT
  2558                              <1> ;		[BP]	: SECTOR #
  2559                              <1> ;		[BP+1]	: TRACK #
  2560                              <1> ;		[BP+2]	: BUFFER OFFSET
  2561                              <1> ;
  2562                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2563                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2564                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2565                              <1> ;	SPECIFIC ERROR CODE.
  2566                              <1> ;
  2567                              <1> 					; (AH) = @DSKETTE_STATUS
  2568 000017D4 FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2569 000017D6 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2570 000017D7 1F                  <1> 	POP	DS
  2571 000017D8 07                  <1> 	pop	es	; 06/02/2015
  2572 000017D9 59                  <1> 	POP	eCX
  2573 000017DA 5B                  <1> 	POP	eBX
  2574 000017DB 5A                  <1> 	POP	eDX
  2575 000017DC 5F                  <1> 	POP	eDI
  2576 000017DD 89E5                <1> 	MOV	eBP, eSP
  2577 000017DF 50                  <1> 	PUSH	eAX
  2578 000017E0 9C                  <1> 	PUSHFd
  2579 000017E1 58                  <1> 	POP	eAX
  2580                              <1> 	;MOV	[BP+6], AX
  2581 000017E2 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2582 000017E5 58                  <1> 	POP	eAX
  2583 000017E6 5D                  <1> 	POP	eBP
  2584 000017E7 CF                  <1> 	IRETd
  2585                              <1> 
  2586                              <1> ;-------------------------------------------------------------------------------
  2587                              <1> ; DW --> dd (06/02/2015)
  2588 000017E8 [4C180000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2589 000017EC [C1180000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2590 000017F0 [D1180000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2591 000017F4 [E2180000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2592 000017F8 [F3180000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2593 000017FC [04190000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2594 00001800 [88190000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2595 00001804 [88190000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2596 00001808 [94190000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2597 0000180C [88190000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2598 00001810 [88190000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2599 00001814 [88190000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2600 00001818 [88190000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2601 0000181C [88190000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2602 00001820 [88190000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2603 00001824 [88190000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2604 00001828 [88190000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2605 0000182C [88190000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2606 00001830 [88190000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2607 00001834 [88190000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2608 00001838 [88190000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2609 0000183C [531A0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2610 00001840 [7B1A0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2611 00001844 [B41A0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2612 00001848 [351B0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2613                              <1> FNC_TAE EQU     $                       ; END
  2614                              <1> 
  2615                              <1> ;-------------------------------------------------------------------------------
  2616                              <1> ; DISK_RESET	(AH = 00H)	
  2617                              <1> ;		RESET THE DISKETTE SYSTEM.
  2618                              <1> ;
  2619                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2620                              <1> ;-------------------------------------------------------------------------------
  2621                              <1> DSK_RESET:
  2622 0000184C 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2623 00001850 FA                  <1> 	CLI				; NO INTERRUPTS
  2624 00001851 A0[1A6D0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2625 00001856 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2626 00001858 C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2627                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2628 0000185B 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2629 0000185D EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2630 0000185E C605[196D0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2631                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2632                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2633                              <1> 					;      PULSE WIDTH)
  2634                              <1> 	; 19/12/2014
  2635                              <1> 	NEWIODELAY
  2108 00001865 E6EB                <2>  out 0EBh,al
  2636                              <1> 
  2637                              <1> 	; 17/12/2014 
  2638                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2639 00001867 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2640                              <1> wdw1:
  2641                              <1> 	NEWIODELAY   ; 27/02/2015
  2108 0000186C E6EB                <2>  out 0EBh,al
  2642 0000186E E2FC                <1> 	loop	wdw1
  2643                              <1> 	;
  2644 00001870 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2645 00001872 EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2646                              <1> 	; 16/12/2014
  2647                              <1> 	IODELAY
  2103 00001873 EB00                <2>  jmp short $+2
  2104 00001875 EB00                <2>  jmp short $+2
  2648                              <1> 	;
  2649                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2650 00001877 E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2651 0000187C 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2652 0000187E 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2653                              <1> NXT_DRV:
  2654                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2655                              <1> 	; 24/12/2021
  2656 00001882 51                  <1> 	push	ecx
  2657 00001883 B8[B7180000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2658 00001888 50                  <1> 	PUSH	eAX			; "
  2659 00001889 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2660 0000188B E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2661 00001890 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2662 00001891 E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2663                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2664                              <1> 	; 24/12/2021
  2665 00001896 59                  <1> 	pop	ecx
  2666 00001897 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2667 00001899 3A0D[1D6D0000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2668 0000189F 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2669 000018A1 FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2670 000018A3 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2671 000018A6 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2672                              <1> 	;
  2673 000018A8 E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2674                              <1> RESBAC:
  2675 000018AD E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2676                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2677                              <1> 	; 24/12/2021
  2678 000018B2 89F3                <1> 	mov	ebx, esi
  2679 000018B4 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2680 000018B6 C3                  <1> 	RETn		
  2681                              <1> DR_POP_ERR:
  2682                              <1> 	;POP	CX			; CLEAR STACK
  2683                              <1> 	; 24/12/2021
  2684 000018B7 59                  <1> 	pop	ecx
  2685                              <1> DR_ERR:
  2686 000018B8 800D[1C6D0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2687 000018BF EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2688                              <1> 
  2689                              <1> ;-------------------------------------------------------------------------------
  2690                              <1> ; DISK_STATUS	(AH = 01H)
  2691                              <1> ;	DISKETTE STATUS.
  2692                              <1> ;
  2693                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2694                              <1> ;
  2695                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2696                              <1> ;-------------------------------------------------------------------------------
  2697                              <1> DSK_STATUS:
  2698 000018C1 8825[1C6D0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2699 000018C7 E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2700                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2701                              <1> 	; 24/12/2021
  2702 000018CC 89F3                <1> 	mov	ebx, esi
  2703 000018CE 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2704 000018D0 C3                  <1> 	RETn		
  2705                              <1> 
  2706                              <1> ;-------------------------------------------------------------------------------
  2707                              <1> ; DISK_READ	(AH = 02H)	
  2708                              <1> ;	DISKETTE READ.
  2709                              <1> ;
  2710                              <1> ; ON ENTRY:	DI	: DRIVE #
  2711                              <1> ;		SI-HI	: HEAD #
  2712                              <1> ;		SI-LOW	: # OF SECTORS
  2713                              <1> ;		ES	: BUFFER SEGMENT
  2714                              <1> ;		[BP]	: SECTOR #
  2715                              <1> ;		[BP+1]	: TRACK #
  2716                              <1> ;		[BP+2]	: BUFFER OFFSET
  2717                              <1> ;
  2718                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2719                              <1> ;-------------------------------------------------------------------------------
  2720                              <1> 
  2721                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2722                              <1> 
  2723                              <1> DSK_READ:
  2724 000018D1 8025[1A6D0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2725 000018D8 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2726 000018DC E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2727 000018E1 C3                  <1> 	RETn
  2728                              <1> 
  2729                              <1> ;-------------------------------------------------------------------------------
  2730                              <1> ; DISK_WRITE	(AH = 03H)
  2731                              <1> ;	DISKETTE WRITE.
  2732                              <1> ;
  2733                              <1> ; ON ENTRY:	DI	: DRIVE #
  2734                              <1> ;		SI-HI	: HEAD #
  2735                              <1> ;		SI-LOW	: # OF SECTORS
  2736                              <1> ;		ES	: BUFFER SEGMENT
  2737                              <1> ;		[BP]	: SECTOR #
  2738                              <1> ;		[BP+1]	: TRACK #
  2739                              <1> ;		[BP+2]	: BUFFER OFFSET
  2740                              <1> ;
  2741                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2742                              <1> ;-------------------------------------------------------------------------------
  2743                              <1> 
  2744                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2745                              <1> 
  2746                              <1> DSK_WRITE:
  2747 000018E2 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2748 000018E6 800D[1A6D0000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2749 000018ED E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2750 000018F2 C3                  <1> 	RETn
  2751                              <1> 
  2752                              <1> ;-------------------------------------------------------------------------------
  2753                              <1> ; DISK_VERF	(AH = 04H)
  2754                              <1> ;	DISKETTE VERIFY.
  2755                              <1> ;
  2756                              <1> ; ON ENTRY:	DI	: DRIVE #
  2757                              <1> ;		SI-HI	: HEAD #
  2758                              <1> ;		SI-LOW	: # OF SECTORS
  2759                              <1> ;		ES	: BUFFER SEGMENT
  2760                              <1> ;		[BP]	: SECTOR #
  2761                              <1> ;		[BP+1]	: TRACK #
  2762                              <1> ;		[BP+2]	: BUFFER OFFSET
  2763                              <1> ;
  2764                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2765                              <1> ;-------------------------------------------------------------------------------
  2766                              <1> DSK_VERF:
  2767 000018F3 8025[1A6D0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2768 000018FA 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2769 000018FE E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2770 00001903 C3                  <1> 	RETn
  2771                              <1> 
  2772                              <1> ;-------------------------------------------------------------------------------
  2773                              <1> ; DISK_FORMAT	(AH = 05H)
  2774                              <1> ;	DISKETTE FORMAT.
  2775                              <1> ;
  2776                              <1> ; ON ENTRY:	DI	: DRIVE #
  2777                              <1> ;		SI-HI	: HEAD #
  2778                              <1> ;		SI-LOW	: # OF SECTORS
  2779                              <1> ;		ES	: BUFFER SEGMENT
  2780                              <1> ;		[BP]	: SECTOR #
  2781                              <1> ;		[BP+1]	: TRACK #
  2782                              <1> ;		[BP+2]	: BUFFER OFFSET
  2783                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2784                              <1> ;
  2785                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2786                              <1> ;-------------------------------------------------------------------------------
  2787                              <1> DSK_FORMAT:
  2788 00001904 E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2789 00001909 E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2790 0000190E 800D[1A6D0000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2791 00001915 E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2792 0000191A 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2793 0000191C E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2794 00001921 E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2795 00001926 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2796 00001928 E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2797                              <1> FM_WR:
  2798 0000192D E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2799 00001932 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2800 00001934 B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2801 00001936 E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2802 0000193B 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2803 0000193D B8[79190000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2804 00001942 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2805 00001943 B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2806 00001945 E80E090000          <1> 	CALL	GET_PARM
  2807 0000194A E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2808 0000194F B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2809 00001951 E802090000          <1> 	CALL	GET_PARM
  2810 00001956 E8030A0000          <1> 	CALL	NEC_OUTPUT
  2811 0000195B B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2812 0000195D E8F6080000          <1> 	CALL	GET_PARM
  2813 00001962 E8F7090000          <1> 	CALL	NEC_OUTPUT
  2814 00001967 B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2815 00001969 E8EA080000          <1> 	CALL	GET_PARM
  2816 0000196E E8EB090000          <1> 	CALL	NEC_OUTPUT
  2817 00001973 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2818 00001974 E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2819                              <1> FM_DON:
  2820 00001979 E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2821 0000197E E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2822                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2823 00001983 89F3                <1> 	mov	ebx, esi ; 24/12/2021
  2824 00001985 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2825 00001987 C3                  <1> 	RETn
  2826                              <1> 
  2827                              <1> ;-------------------------------------------------------------------------------
  2828                              <1> ; FNC_ERR
  2829                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2830                              <1> ;	SET BAD COMMAND IN STATUS.
  2831                              <1> ;
  2832                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2833                              <1> ;-------------------------------------------------------------------------------
  2834                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2835                              <1> 	;MOV	AX,SI			; RESTORE AL
  2836                              <1> 	; 24/12/2021
  2837 00001988 89F0                <1> 	mov	eax, esi
  2838 0000198A B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2839 0000198C 8825[1C6D0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2840 00001992 F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2841 00001993 C3                  <1> 	RETn
  2842                              <1> 
  2843                              <1> ;-------------------------------------------------------------------------------
  2844                              <1> ; DISK_PARMS	(AH = 08H)	
  2845                              <1> ;	READ DRIVE PARAMETERS.
  2846                              <1> ;
  2847                              <1> ; ON ENTRY:	DI : DRIVE #
  2848                              <1> ;
  2849                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2850                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2851                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2852                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2853                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2854                              <1> ;		BH/[BP+3] = 0
  2855                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2856                              <1> ;		DH/[BP+5] = MAX HEAD #
  2857                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2858                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2859                              <1> ;		AX        = 0
  2860                              <1> ;
  2861                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2862                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2863                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2864                              <1> ;		       CALLER.
  2865                              <1> ;-------------------------------------------------------------------------------
  2866                              <1> DSK_PARMS:
  2867 00001994 E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2868                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2869 00001999 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2870 0000199B 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2871                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2872                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2873                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2874                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2875                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2876                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2877                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2878                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2879                              <1> 	;sub	edx, edx
  2880 0000199E 66A1[8E670000]      <1> 	mov     ax, [fd0_type]
  2881 000019A4 6621C0              <1> 	and     ax, ax
  2882 000019A7 7473                <1> 	jz      short NON_DRV
  2883 000019A9 FEC2                <1> 	inc     dl
  2884 000019AB 20E4                <1> 	and     ah, ah
  2885 000019AD 7402                <1> 	jz      short STO_DL
  2886 000019AF FEC2                <1> 	inc     dl
  2887                              <1> STO_DL:
  2888                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2889 000019B1 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2890 000019B4 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2891 000019B8 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2892                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2893 000019BA C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2894 000019BE E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2895                              <1> 	;;20/02/2015
  2896                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2897                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2898 000019C3 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2899 000019C5 E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2900 000019CA 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2901                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2902 000019CC 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2903 000019CF 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2904 000019D2 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2905 000019D5 EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2906                              <1> CHK_EST:
  2907 000019D7 8AA7[296D0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2908 000019DD F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2909 000019E0 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2910                              <1> USE_EST:
  2911 000019E2 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2912 000019E5 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2913 000019E8 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2914                              <1> 
  2915                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2916                              <1> 
  2917 000019EA B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2918 000019EC E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2919 000019F1 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2920 000019F4 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2921 000019F7 F687[296D0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2922 000019FE 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2923                              <1> 
  2924                              <1> ;-----	IT IS 1.44 MB DRIVE
  2925                              <1> 
  2926                              <1> PARM144:
  2927 00001A00 B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2928 00001A02 E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2929 00001A07 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2930 00001A0A 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2931                              <1> STO_CX:
  2932 00001A0D 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2933                              <1> ES_DI:
  2934                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2935 00001A10 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2936                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2937                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2938                              <1> DP_OUT:
  2939 00001A13 E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2940                              <1> 	;XOR	AX,AX			; CLEAR
  2941                              <1> 	; 24/12/2021
  2942 00001A18 31C0                <1> 	xor	eax, eax
  2943 00001A1A F8                  <1> 	CLC
  2944 00001A1B C3                  <1> 	RETn
  2945                              <1> 
  2946                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2947                              <1> 
  2948                              <1> NON_DRV:
  2949                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  2950 00001A1C 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  2951                              <1> NON_DRV1:
  2952 00001A1F 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  2953 00001A24 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  2954                              <1> 
  2955                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  2956                              <1> 	
  2957 00001A26 E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  2958                              <1> 	;MOV	AX,SI			; RESTORE AL
  2959 00001A2B 89F0                <1> 	mov	eax, esi ; 24/12/2021
  2960 00001A2D B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2961 00001A2F F9                  <1> 	STC
  2962 00001A30 C3                  <1> 	RETn
  2963                              <1> 
  2964                              <1> NON_DRV2:
  2965                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  2966 00001A31 31C0                <1> 	xor	eax, eax	
  2967 00001A33 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  2968                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  2969 00001A37 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  2970                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  2971 00001A3A 89450C              <1> 	mov	[ebp+12], eax
  2972                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2973 00001A3D EBD4                <1> 	JMP	SHORT DP_OUT
  2974                              <1> 
  2975                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  2976                              <1> 
  2977                              <1> USE_EST2:
  2978 00001A3F B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  2979 00001A41 E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2980 00001A46 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2981 00001A49 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2982 00001A4C 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  2983 00001A4F 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  2984 00001A51 EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  2985                              <1> 
  2986                              <1> ;-------------------------------------------------------------------------------
  2987                              <1> ; DISK_TYPE (AH = 15H)	
  2988                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  2989                              <1> ;
  2990                              <1> ;  ON ENTRY:	DI = DRIVE #
  2991                              <1> ;
  2992                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  2993                              <1> ;-------------------------------------------------------------------------------
  2994                              <1> DSK_TYPE:
  2995 00001A53 E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2996 00001A58 8A87[296D0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  2997 00001A5E 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  2998 00001A60 7415                <1> 	JZ	short NO_DRV
  2999 00001A62 B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  3000 00001A64 A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  3001 00001A66 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  3002 00001A68 B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  3003                              <1> DT_BACK:
  3004                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  3005 00001A6A 50                  <1> 	push	eax ; 24/12/2021
  3006 00001A6B E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3007                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  3008 00001A70 58                  <1> 	pop	eax ; 24/12/2021
  3009 00001A71 F8                  <1> 	CLC				; NO ERROR
  3010                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3011                              <1> 	; 24/12/2021
  3012 00001A72 89F3                <1> 	mov	ebx, esi
  3013 00001A74 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3014 00001A76 C3                  <1> 	RETn
  3015                              <1> NO_DRV:	
  3016 00001A77 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  3017 00001A79 EBEF                <1> 	JMP	SHORT DT_BACK
  3018                              <1> 
  3019                              <1> ;-------------------------------------------------------------------------------
  3020                              <1> ; DISK_CHANGE	(AH = 16H)
  3021                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  3022                              <1> ;
  3023                              <1> ; ON ENTRY:	DI = DRIVE #
  3024                              <1> ;
  3025                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  3026                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  3027                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  3028                              <1> ;-------------------------------------------------------------------------------
  3029                              <1> DSK_CHANGE:
  3030 00001A7B E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3031 00001A80 8A87[296D0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  3032 00001A86 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  3033 00001A88 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  3034 00001A8A A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  3035 00001A8C 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  3036                              <1> DC0:
  3037 00001A8E E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  3038 00001A93 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  3039                              <1> 
  3040 00001A95 C605[1C6D0000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  3041                              <1> 
  3042 00001A9C E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3043 00001AA1 E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3044                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3045                              <1> 	; 24/12/2021
  3046 00001AA6 89F3                <1> 	mov	ebx, esi
  3047 00001AA8 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3048 00001AAA C3                  <1> 	RETn
  3049                              <1> DC_NON:
  3050 00001AAB 800D[1C6D0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  3051 00001AB2 EBE8                <1> 	JMP	SHORT FINIS
  3052                              <1> 
  3053                              <1> ;-------------------------------------------------------------------------------
  3054                              <1> ; FORMAT_SET	(AH = 17H)
  3055                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  3056                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  3057                              <1> ;
  3058                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3059                              <1> ;		DI     = DRIVE #
  3060                              <1> ;
  3061                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3062                              <1> ;		AH = @DSKETTE_STATUS
  3063                              <1> ;		CY = 1 IF ERROR
  3064                              <1> ;-------------------------------------------------------------------------------
  3065                              <1> FORMAT_SET:
  3066 00001AB4 E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3067                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3068                              <1> 	; 24/12/2021
  3069 00001AB9 56                  <1> 	push	esi
  3070 00001ABA 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3071 00001ABD 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3072 00001ABF 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3073 00001AC2 80A7[296D0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3074 00001AC9 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3075 00001ACB 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3076 00001ACD 808F[296D0000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3077 00001AD4 EB48                <1> 	JMP	SHORT S0
  3078                              <1> NOT_320:
  3079 00001AD6 E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3080 00001ADB 803D[1C6D0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3081 00001AE2 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3082                              <1> S3:
  3083 00001AE4 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3084 00001AE6 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3085 00001AE8 808F[296D0000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3086 00001AEF EB2D                <1> 	JMP	SHORT S0
  3087                              <1> NOT_320_12:
  3088 00001AF1 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3089 00001AF3 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3090 00001AF5 808F[296D0000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3091 00001AFC EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3092                              <1> NOT_12:	
  3093 00001AFE 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3094 00001B00 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3095                              <1> 
  3096 00001B02 F687[296D0000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3097 00001B09 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3098 00001B0B B050                <1> 	MOV	AL,MED_DET+RATE_300
  3099 00001B0D F687[296D0000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3100 00001B14 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3101                              <1> ASSUME:
  3102 00001B16 B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3103                              <1> OR_IT_IN:
  3104 00001B18 0887[296D0000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3105                              <1> S0:
  3106 00001B1E E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3107 00001B23 E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3108                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3109                              <1> 	; 24/12/2021
  3110 00001B28 5B                  <1> 	pop	ebx
  3111 00001B29 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3112 00001B2B C3                  <1> 	RETn
  3113                              <1> FS_ERR:
  3114 00001B2C C605[1C6D0000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3115 00001B33 EBE9                <1> 	JMP	SHORT S0
  3116                              <1> 
  3117                              <1> ;-------------------------------------------------------------------------------
  3118                              <1> ; SET_MEDIA	(AH = 18H)
  3119                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3120                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3121                              <1> ;
  3122                              <1> ; ON ENTRY:
  3123                              <1> ;	[BP]	= SECTOR PER TRACK
  3124                              <1> ;	[BP+1]	= TRACK #
  3125                              <1> ;	DI	= DRIVE #
  3126                              <1> ;
  3127                              <1> ; ON EXIT:
  3128                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3129                              <1> ;	IF NO ERROR:
  3130                              <1> ;		AH = 0
  3131                              <1> ;		CY = 0
  3132                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3133                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3134                              <1> ;	IF ERROR:	
  3135                              <1> ;		AH = @DSKETTE_STATUS
  3136                              <1> ;		CY = 1
  3137                              <1> ;-------------------------------------------------------------------------------
  3138                              <1> SET_MEDIA:
  3139 00001B35 E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3140 00001B3A F687[296D0000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3141 00001B41 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3142 00001B43 E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3143 00001B48 803D[1C6D0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3144 00001B4F 746B                <1> 	JE	short SM_RTN
  3145 00001B51 C605[1C6D0000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3146                              <1> SM_CMOS:
  3147 00001B58 E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3148                              <1> 	;;20/02/2015
  3149                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3150                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3151 00001B5D 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3152 00001B5F E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3153 00001B64 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3154 00001B66 57                  <1> 	PUSH	eDI			; SAVE REG.
  3155 00001B67 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3156 00001B69 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3157                              <1> DR_SEARCH:
  3158 00001B6E 8AA3[0C670000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3159 00001B74 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3160 00001B77 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3161 00001B79 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3162                              <1> DR_FND:
  3163 00001B7B 8BBB[0D670000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3164                              <1> MD_SEARCH:
  3165 00001B81 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3166 00001B84 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3167 00001B87 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3168 00001B89 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3169 00001B8C 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3170 00001B8F 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3171                              <1> NXT_MD:
  3172                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3173 00001B91 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3174 00001B94 E2D8                <1> 	LOOP    DR_SEARCH
  3175 00001B96 5F                  <1> 	POP	eDI			; RESTORE REG.
  3176                              <1> MD_NOT_FND:
  3177 00001B97 C605[1C6D0000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3178 00001B9E EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3179                              <1> MD_FND:
  3180 00001BA0 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3181 00001BA3 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3182 00001BA5 7502                <1> 	JNE	short MD_SET
  3183 00001BA7 0C20                <1> 	OR	AL,DBL_STEP
  3184                              <1> MD_SET:
  3185                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3186 00001BA9 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3187 00001BAC 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3188 00001BAE 5F                  <1> 	POP	eDI
  3189 00001BAF 80A7[296D0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3190 00001BB6 0887[296D0000]      <1> 	OR	[DSK_STATE+eDI], AL
  3191                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3192                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3193                              <1> SM_RTN:
  3194 00001BBC E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3195 00001BC1 E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3196 00001BC6 C3                  <1> 	RETn
  3197                              <1> 
  3198                              <1> ;----------------------------------------------------------------
  3199                              <1> ; DR_TYPE_CHECK							:
  3200                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3201                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3202                              <1> ; ON ENTRY:							:
  3203                              <1> ;	AL = DRIVE TYPE						:
  3204                              <1> ; ON EXIT:							:
  3205                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3206                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3207                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3208                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3209                              <1> ; REGISTERS ALTERED: eBX						:
  3210                              <1> ;----------------------------------------------------------------		
  3211                              <1> DR_TYPE_CHECK:
  3212                              <1> 	;PUSH	AX			
  3213                              <1> 	; 24/12/2021
  3214 00001BC7 50                  <1> 	push	eax
  3215 00001BC8 51                  <1> 	PUSH	eCX
  3216 00001BC9 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3217 00001BCB B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3218                              <1> TYPE_CHK:	
  3219 00001BD0 8AA3[0C670000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3220 00001BD6 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3221 00001BD8 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3222                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3223 00001BDA 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3224 00001BDD E2F1                <1> 	LOOP    TYPE_CHK
  3225                              <1> 	;
  3226 00001BDF BB[6B670000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3227                              <1> 					; Default for GET_PARM (11/12/2014)
  3228                              <1> 	;
  3229 00001BE4 F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3230 00001BE5 EB06                <1> 	JMP	SHORT TYPE_RTN
  3231                              <1> DR_TYPE_VALID:
  3232 00001BE7 8B9B[0D670000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3233                              <1> TYPE_RTN:
  3234 00001BED 59                  <1> 	POP	eCX
  3235                              <1> 	;POP	AX
  3236                              <1> 	; 24/12/2021
  3237 00001BEE 58                  <1> 	pop	eax
  3238 00001BEF C3                  <1> 	RETn	
  3239                              <1> 		
  3240                              <1> ;----------------------------------------------------------------
  3241                              <1> ; SEND_SPEC							:
  3242                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3243                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3244                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3245                              <1> ; ON EXIT:	NONE						:	
  3246                              <1> ; REGISTERS ALTERED: CX, DX					:
  3247                              <1> ;----------------------------------------------------------------		
  3248                              <1> SEND_SPEC:
  3249 00001BF0 50                  <1> 	PUSH	eAX			; SAVE AX
  3250 00001BF1 B8[171C0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3251 00001BF6 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3252 00001BF7 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3253 00001BF9 E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3254 00001BFE 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3255 00001C00 E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3256 00001C05 E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3257 00001C0A B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3258 00001C0C E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3259 00001C11 E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3260 00001C16 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3261                              <1> SPECBAC:
  3262 00001C17 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3263 00001C18 C3                  <1> 	RETn
  3264                              <1> 
  3265                              <1> ;----------------------------------------------------------------
  3266                              <1> ; SEND_SPEC_MD							:
  3267                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3268                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3269                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3270                              <1> ; ON EXIT:	NONE						:	
  3271                              <1> ; REGISTERS ALTERED: AX						:
  3272                              <1> ;----------------------------------------------------------------		
  3273                              <1> SEND_SPEC_MD:
  3274 00001C19 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3275 00001C1A B8[371C0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3276 00001C1F 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3277 00001C20 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3278 00001C22 E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3279 00001C27 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3280 00001C29 E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3281 00001C2E 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3282 00001C31 E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3283 00001C36 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3284                              <1> SPEC_ESBAC:
  3285 00001C37 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3286 00001C38 C3                  <1> 	RETn
  3287                              <1> 
  3288                              <1> ;-------------------------------------------------------------------------------
  3289                              <1> ; XLAT_NEW  
  3290                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3291                              <1> ;	MODE TO NEW ARCHITECTURE.
  3292                              <1> ;
  3293                              <1> ; ON ENTRY:	DI = DRIVE #
  3294                              <1> ;-------------------------------------------------------------------------------
  3295                              <1> XLAT_NEW:
  3296 00001C39 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3297 00001C3C 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3298 00001C3E 80BF[296D0000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3299 00001C45 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3300 00001C47 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3301 00001C4A C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3302 00001C4D A0[286D0000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3303 00001C52 D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3304 00001C54 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3305 00001C56 80A7[296D0000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3306 00001C5D 0887[296D0000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3307                              <1> XN_OUT:
  3308 00001C63 C3                  <1> 	RETn
  3309                              <1> DO_DET:
  3310 00001C64 E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3311 00001C69 C3                  <1> 	RETn
  3312                              <1> 
  3313                              <1> ;-------------------------------------------------------------------------------
  3314                              <1> ; XLAT_OLD 
  3315                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3316                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3317                              <1> ;
  3318                              <1> ; ON ENTRY:	DI = DRIVE
  3319                              <1> ;-------------------------------------------------------------------------------
  3320                              <1> XLAT_OLD:
  3321 00001C6A 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3322                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3323                              <1>         ;ja	XO_OUT
  3324                              <1>         ; 24/12/2021
  3325 00001C6D 77F4                <1> 	ja	short XN_OUT
  3326 00001C6F 80BF[296D0000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3327 00001C76 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3328                              <1> 
  3329                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3330                              <1> 
  3331 00001C78 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3332 00001C7B C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3333 00001C7E B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3334 00001C80 D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3335 00001C82 8425[286D0000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3336 00001C88 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3337                              <1> 
  3338                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3339                              <1> 
  3340 00001C8A B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3341 00001C8C D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3342 00001C8E F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3343 00001C90 2025[286D0000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3344                              <1> 
  3345                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3346                              <1> 
  3347 00001C96 8A87[296D0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3348 00001C9C 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3349 00001C9E D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3350 00001CA0 0805[286D0000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3351                              <1> 
  3352                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3353                              <1> 
  3354                              <1> SAVE_SET:
  3355 00001CA6 8AA7[296D0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3356 00001CAC 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3357 00001CAE 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3358 00001CB1 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3359 00001CB4 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3360 00001CB6 B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3361 00001CB8 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3362 00001CBB 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3363 00001CBD F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3364 00001CC0 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3365                              <1> UNKNO:
  3366 00001CC2 B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3367 00001CC4 EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3368                              <1> CHK_144:
  3369 00001CC6 E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3370                              <1> 	;;20/02/2015
  3371                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3372 00001CCB 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3373 00001CCD 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3374 00001CCF 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3375 00001CD1 B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3376 00001CD3 EB0C                <1> 	JMP	SHORT TST_DET
  3377                              <1> CHK_250:
  3378 00001CD5 B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3379 00001CD7 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3380 00001CDA 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3381 00001CDC F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3382 00001CDF 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3383                              <1> TST_DET:
  3384 00001CE1 F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3385 00001CE4 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3386 00001CE6 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3387                              <1> AL_SET:
  3388 00001CE8 80A7[296D0000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3389 00001CEF 0887[296D0000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3390                              <1> XO_OUT:
  3391 00001CF5 C3                  <1> 	RETn
  3392                              <1> 
  3393                              <1> ;-------------------------------------------------------------------------------
  3394                              <1> ; RD_WR_VF
  3395                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3396                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3397                              <1> ;
  3398                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3399                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3400                              <1> ;
  3401                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3402                              <1> ;-------------------------------------------------------------------------------
  3403                              <1> RD_WR_VF:
  3404                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3405 00001CF6 50                  <1> 	push	eax ; 24/12/2021
  3406 00001CF7 E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3407 00001CFC E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3408                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3409 00001D01 58                  <1> 	pop	eax ; 24/12/2021
  3410                              <1> DO_AGAIN:
  3411                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3412 00001D02 50                  <1> 	push	eax ; 24/12/2021
  3413 00001D03 E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3414                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3415 00001D08 58                  <1> 	pop	eax ; 24/12/2021
  3416                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3417                              <1> 	; 24/12/2021
  3418 00001D09 7305                <1> 	jnc	short RWV
  3419 00001D0B E9C3000000          <1> 	jmp	RWV_END
  3420                              <1> RWV:
  3421                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3422 00001D10 50                  <1> 	push	eax ; 24/12/2021
  3423 00001D11 8AB7[296D0000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3424 00001D17 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3425 00001D1A E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3426                              <1> 	;;20/02/2015
  3427                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3428 00001D1F 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3429 00001D21 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3430 00001D23 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3431 00001D25 F687[296D0000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3432 00001D2C 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3433 00001D2E B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3434 00001D30 EB0F                <1> 	JMP	SHORT RWV_2
  3435                              <1> RWV_1:
  3436 00001D32 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3437 00001D34 F687[296D0000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3438 00001D3B 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3439 00001D3D B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3440 00001D3F EB04                <1> 	jmp	short rwv_3
  3441                              <1> RWV_2:
  3442 00001D41 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3443 00001D43 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3444                              <1> rwv_3:
  3445 00001D45 E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3446 00001D4A 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3447                              <1> 
  3448                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3449                              <1> 
  3450 00001D4C 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3451 00001D4D 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3452 00001D4F B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3453                              <1> RWV_DR_SEARCH:
  3454 00001D54 8AA3[0C670000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3455 00001D5A 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3456 00001D5D 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3457 00001D5F 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3458                              <1> RWV_DR_FND:
  3459 00001D61 8BBB[0D670000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3460                              <1> RWV_MD_SEARH:
  3461 00001D67 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3462 00001D6A 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3463                              <1> RWV_NXT_MD:
  3464                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3465 00001D6C 83C305              <1> 	add	eBX, 5
  3466 00001D6F E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3467 00001D71 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3468                              <1> 
  3469                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3470                              <1> 
  3471                              <1> RWV_ASSUME:
  3472 00001D72 BB[2A670000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3473 00001D77 F687[296D0000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3474 00001D7E 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3475 00001D80 BB[44670000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3476 00001D85 EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3477                              <1> 
  3478                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3479                              <1> 	 			
  3480                              <1> RWV_MD_FND:
  3481 00001D87 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3482 00001D89 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3483                              <1> 	
  3484                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3485                              <1> 
  3486                              <1> RWV_MD_FND1:
  3487 00001D8A E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3488 00001D8F E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3489 00001D94 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3490 00001D96 E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3491                              <1> RWV_DBL:
  3492 00001D9B 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3493 00001D9C E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3494 00001DA1 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3495 00001DA2 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3496                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3497 00001DA4 58                  <1> 	pop	eax ; 24/12/2021
  3498                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3499 00001DA5 50                  <1> 	push	eax ; 24/12/2021
  3500 00001DA6 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3501 00001DA7 E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3502 00001DAC 5B                  <1> 	POP	eBX 
  3503                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3504 00001DAD 58                  <1> 	pop	eax ; 24/12/2021
  3505 00001DAE 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3506                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3507 00001DB0 50                  <1> 	push	eax ; 24/12/2021
  3508 00001DB1 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3509 00001DB2 E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3510 00001DB7 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3511 00001DB8 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3512 00001DBA E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3513 00001DBF 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3514 00001DC1 E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3515                              <1> CHK_RET:
  3516 00001DC6 E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3517                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3518 00001DCB 58                  <1> 	pop	eax ; 24/12/2021
  3519 00001DCC 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3520 00001DCE E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3521                              <1> RWV_END:
  3522 00001DD3 E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3523 00001DD8 E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3524                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3525                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3526 00001DDD 50                  <1> 	push	eax ; 24/12/2021
  3527 00001DDE E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3528                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3529 00001DE3 58                  <1> 	pop	eax ; 24/12/2021
  3530 00001DE4 E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3531 00001DE9 C3                  <1> 	RETn
  3532                              <1> 
  3533                              <1> ;-------------------------------------------------------------------------------
  3534                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3535                              <1> ;-------------------------------------------------------------------------------
  3536                              <1> SETUP_STATE:
  3537 00001DEA F687[296D0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3538 00001DF1 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3539 00001DF3 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3540 00001DF7 F687[296D0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3541 00001DFE 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3542 00001E00 F687[296D0000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3543 00001E07 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3544 00001E09 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3545                              <1> AX_SET:	
  3546 00001E0D 80A7[296D0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3547 00001E14 08A7[296D0000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3548 00001E1A 8025[246D0000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3549 00001E21 C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3550 00001E24 0805[246D0000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3551                              <1> J1C:	
  3552 00001E2A C3                  <1> 	RETn
  3553                              <1> 
  3554                              <1> ;-------------------------------------------------------------------------------
  3555                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3556                              <1> ;-------------------------------------------------------------------------------
  3557                              <1> FMT_INIT:
  3558 00001E2B F687[296D0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3559 00001E32 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3560 00001E34 E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3561                              <1> 	;; 20/02/2015
  3562                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3563 00001E39 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3564 00001E3B FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3565                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3566 00001E3D 8AA7[296D0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3567 00001E43 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3568 00001E46 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3569 00001E48 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3570 00001E4A 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3571 00001E4D EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3572                              <1> N_360:	
  3573 00001E4F FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3574 00001E51 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3575                              <1> F1_RATE:
  3576 00001E53 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3577 00001E56 EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3578                              <1> N_12:	
  3579 00001E58 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3580 00001E5A 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3581 00001E5C F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3582 00001E5F 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3583 00001E61 F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3584 00001E64 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3585 00001E66 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3586 00001E69 EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3587                              <1> N_720:
  3588 00001E6B FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3589 00001E6D 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3590 00001E6F EBE2                <1> 	JMP	SHORT F1_RATE
  3591                              <1> ISNT_12: 
  3592 00001E71 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3593                              <1> 
  3594                              <1> SKP_STATE:
  3595 00001E74 88A7[296D0000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3596                              <1> F1_OUT:
  3597 00001E7A C3                  <1> 	RETn
  3598                              <1> CL_DRV:	
  3599 00001E7B 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3600 00001E7D EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3601                              <1> 
  3602                              <1> ;-------------------------------------------------------------------------------
  3603                              <1> ; MED_CHANGE	
  3604                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3605                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3606                              <1> ;
  3607                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3608                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3609                              <1> ;-------------------------------------------------------------------------------
  3610                              <1> MED_CHANGE:
  3611 00001E7F E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3612 00001E84 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3613 00001E86 80A7[296D0000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3614                              <1> 
  3615                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3616                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3617                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3618                              <1> 
  3619 00001E8D 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3620 00001E90 B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3621 00001E92 D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3622 00001E94 F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3623 00001E96 FA                  <1> 	CLI				; NO INTERRUPTS
  3624 00001E97 2005[1A6D0000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3625 00001E9D FB                  <1> 	STI				; INTERRUPTS ENABLED
  3626 00001E9E E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3627                              <1> 
  3628                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3629                              <1> 
  3630 00001EA3 E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3631 00001EA8 B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3632 00001EAA E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3633 00001EAF 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3634 00001EB1 E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3635 00001EB6 C605[1C6D0000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3636                              <1> OK1:
  3637 00001EBD E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3638 00001EC2 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3639                              <1> OK4:
  3640 00001EC4 C605[1C6D0000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3641                              <1> OK2:		
  3642 00001ECB F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3643 00001ECC C3                  <1> 	RETn
  3644                              <1> MC_OUT:
  3645 00001ECD F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3646 00001ECE C3                  <1> 	RETn
  3647                              <1> 
  3648                              <1> ;-------------------------------------------------------------------------------
  3649                              <1> ; SEND_RATE
  3650                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3651                              <1> ; ON ENTRY:	DI = DRIVE #
  3652                              <1> ; ON EXIT:	NONE
  3653                              <1> ; REGISTERS ALTERED: DX
  3654                              <1> ;-------------------------------------------------------------------------------
  3655                              <1> SEND_RATE:
  3656                              <1> 	;PUSH	AX			; SAVE REG.
  3657                              <1> 	; 24/12/2021
  3658 00001ECF 50                  <1> 	push	eax
  3659 00001ED0 8025[246D0000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3660 00001ED7 8A87[296D0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3661 00001EDD 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3662 00001EDF 0805[246D0000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3663 00001EE5 C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3664 00001EE8 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3665 00001EEC EE                  <1> 	OUT	DX,AL
  3666                              <1> 	;POP	AX			; RESTORE REG.
  3667                              <1> 	; 24/12/2021
  3668 00001EED 58                  <1> 	pop	eax
  3669 00001EEE C3                  <1> 	RETn
  3670                              <1> 
  3671                              <1> ;-------------------------------------------------------------------------------
  3672                              <1> ; CHK_LASTRATE
  3673                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3674                              <1> ; ON ENTRY:
  3675                              <1> ;	DI = DRIVE #
  3676                              <1> ; ON EXIT:
  3677                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3678                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3679                              <1> ; REGISTERS ALTERED: DX
  3680                              <1> ;-------------------------------------------------------------------------------
  3681                              <1> CHK_LASTRATE:
  3682                              <1> 	;PUSH	AX			; SAVE REG.
  3683                              <1> 	; 24/12/2021
  3684 00001EEF 50                  <1> 	push	eax
  3685 00001EF0 2225[246D0000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3686 00001EF6 8A87[296D0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3687 00001EFC 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3688 00001F00 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3689                              <1> 					; ZF = 1 RATE IS THE SAME
  3690                              <1> 	;POP	AX			; RESTORE REG.
  3691                              <1> 	; 24/12/2021
  3692 00001F02 58                  <1> 	pop	eax
  3693 00001F03 C3                  <1> 	RETn
  3694                              <1> 
  3695                              <1> ;-------------------------------------------------------------------------------
  3696                              <1> ; DMA_SETUP
  3697                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3698                              <1> ;
  3699                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3700                              <1> ;
  3701                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3702                              <1> ;-------------------------------------------------------------------------------
  3703                              <1> 
  3704                              <1> ; SI = Head #, # of Sectors or DASD Type
  3705                              <1> 
  3706                              <1> ; 22/08/2015
  3707                              <1> ; 08/02/2015 - Protected Mode Modification
  3708                              <1> ; 06/02/2015 - 07/02/2015
  3709                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3710                              <1> ; (DMA Addres = Physical Address)
  3711                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3712                              <1> ;
  3713                              <1> ; 04/02/2016 (clc)
  3714                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3715                              <1> ; 16/12/2014 (IODELAY)
  3716                              <1> 
  3717                              <1> DMA_SETUP:
  3718                              <1> 
  3719                              <1> ;; 20/02/2015
  3720 00001F04 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3721 00001F07 F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3722 00001F0D 7569                <1> 	jnz	short dma_bnd_err_stc
  3723                              <1> 	;
  3724                              <1> 	;push	ax			; DMA command
  3725                              <1> 	; 24/12/2021
  3726 00001F0F 50                  <1> 	push	eax
  3727 00001F10 52                  <1> 	push	edx			; *
  3728 00001F11 B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3729 00001F13 E840030000          <1> 	call	GET_PARM		; 
  3730 00001F18 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3731                              <1> 	;mov	ax, si			; Sector count
  3732                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3733                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3734                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3735                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3736                              <1> 	; 24/12/2021
  3737 00001F1A 89F2                <1> 	mov	edx, esi
  3738 00001F1C 29C0                <1> 	sub	eax, eax
  3739 00001F1E 88D4                <1> 	mov	ah, dl
  3740 00001F20 D1E8                <1> 	shr	eax, 1
  3741 00001F22 D3E0                <1> 	shl	eax, cl
  3742                              <1> 	;
  3743 00001F24 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3744 00001F26 6689C1              <1> 	mov	cx, ax
  3745 00001F29 5A                  <1> 	pop	edx			; *
  3746                              <1> 	;pop	ax
  3747                              <1> 	; 24/12/2021
  3748 00001F2A 58                  <1> 	pop	eax
  3749 00001F2B 3C42                <1> 	cmp	al, 42h
  3750 00001F2D 7507                <1>         jne     short NOT_VERF
  3751 00001F2F BA0000FF00          <1> 	mov	edx, 0FF0000h
  3752 00001F34 EB08                <1> 	jmp	short J33
  3753                              <1> NOT_VERF:
  3754 00001F36 6601CA              <1> 	add	dx, cx			; check for overflow
  3755 00001F39 723E                <1> 	jc	short dma_bnd_err
  3756                              <1> 	;
  3757 00001F3B 6629CA              <1> 	sub	dx, cx			; Restore start address
  3758                              <1> J33:
  3759 00001F3E FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3760 00001F3F E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3761                              <1> 	IODELAY				; WAIT FOR I/O
  2103 00001F41 EB00                <2>  jmp short $+2
  2104 00001F43 EB00                <2>  jmp short $+2
  3762 00001F45 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3763 00001F47 89D0                <1> 	mov	eax,edx			; Buffer address
  3764 00001F49 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3765                              <1> 	IODELAY				; WAIT FOR I/O
  2103 00001F4B EB00                <2>  jmp short $+2
  2104 00001F4D EB00                <2>  jmp short $+2
  3766 00001F4F 88E0                <1> 	MOV	AL,AH
  3767 00001F51 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3768 00001F53 C1E810              <1> 	shr	eax,16
  3769                              <1> 	IODELAY				; I/O WAIT STATE
  2103 00001F56 EB00                <2>  jmp short $+2
  2104 00001F58 EB00                <2>  jmp short $+2
  3770 00001F5A E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3771                              <1> 	IODELAY
  2103 00001F5C EB00                <2>  jmp short $+2
  2104 00001F5E EB00                <2>  jmp short $+2
  3772 00001F60 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3773 00001F63 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3774                              <1> 	IODELAY				; WAIT FOR I/O
  2103 00001F65 EB00                <2>  jmp short $+2
  2104 00001F67 EB00                <2>  jmp short $+2
  3775 00001F69 88E0                <1> 	MOV	AL,AH
  3776 00001F6B E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3777                              <1> 	IODELAY
  2103 00001F6D EB00                <2>  jmp short $+2
  2104 00001F6F EB00                <2>  jmp short $+2
  3778 00001F71 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3779 00001F72 B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3780 00001F74 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3781                              <1> 
  3782 00001F76 F8                  <1> 	clc	; 04/02/2016
  3783 00001F77 C3                  <1> 	retn
  3784                              <1> 
  3785                              <1> dma_bnd_err_stc:
  3786 00001F78 F9                  <1> 	stc
  3787                              <1> dma_bnd_err:
  3788 00001F79 C605[1C6D0000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3789 00001F80 C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3790                              <1> 
  3791                              <1> ;; 16/12/2014
  3792                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3793                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3794                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3795                              <1> ;;	IODELAY
  3796                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3797                              <1> ;;	;SIODELAY
  3798                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3799                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3800                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3801                              <1> ;;      ;JMP	SHORT J33
  3802                              <1> ;;;NOT_VERF:	
  3803                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3804                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3805                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3806                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3807                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3808                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3809                              <1> ;;	;JNC	short J33
  3810                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3811                              <1> ;;;J33:
  3812                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3813                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3814                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3815                              <1> ;;	IODELAY
  3816                              <1> ;;	MOV	AL,AH
  3817                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3818                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3819                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3820                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3821                              <1> ;;	IODELAY
  3822                              <1> ;;	;AND	AL,00001111B
  3823                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3824                              <1> ;;	;SIODELAY
  3825                              <1> ;;
  3826                              <1> ;;;----- DETERMINE COUNT
  3827                              <1> ;;	sub	eax, eax ; 08/02/2015
  3828                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3829                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3830                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3831                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3832                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3833                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3834                              <1> ;;	CALL	GET_PARM		; "
  3835                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3836                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3837                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3838                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3839                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3840                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3841                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3842                              <1> ;;	IODELAY
  3843                              <1> ;;	MOV	AL, AH
  3844                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3845                              <1> ;;	;IODELAY
  3846                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3847                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3848                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3849                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3850                              <1> ;;	add	ecx, eax ; 08/02/2015
  3851                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3852                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3853                              <1> ;;	SIODELAY
  3854                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3855                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3856                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3857                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3858                              <1> ;;	jz	short NO_BAD
  3859                              <1> ;;dma_bnd_err:
  3860                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3861                              <1> ;;NO_BAD:
  3862                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3863                              <1> 
  3864                              <1> ;-------------------------------------------------------------------------------
  3865                              <1> ; FMTDMA_SET
  3866                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3867                              <1> ;
  3868                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3869                              <1> ;
  3870                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3871                              <1> ;-------------------------------------------------------------------------------
  3872                              <1> 
  3873                              <1> 	; 24/12/2021
  3874                              <1> FMTDMA_SET:
  3875                              <1> ;; 20/02/2015 modification	
  3876 00001F81 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3877 00001F84 F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3878 00001F8A 75EC                <1> 	jnz	short dma_bnd_err_stc
  3879                              <1> 	;
  3880                              <1> 	;push	dx			; *
  3881                              <1> 	; 24/12/2021
  3882 00001F8C 52                  <1> 	push	edx
  3883 00001F8D B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3884 00001F8F E8C4020000          <1> 	call	GET_PARM		; "
  3885                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3886                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3887                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3888                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3889                              <1> 	;mov	cx, ax
  3890                              <1> 	; 24/12/2021
  3891 00001F94 29C9                <1> 	sub	ecx, ecx
  3892 00001F96 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3893 00001F98 D1E1                <1> 	shl	ecx, 1
  3894 00001F9A D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3895 00001F9C 6649                <1> 	dec	cx
  3896                              <1> 	;pop	dx			; *
  3897                              <1> 	; 24/12/2021
  3898 00001F9E 5A                  <1> 	pop	edx
  3899 00001F9F 6601CA              <1> 	add	dx, cx			; check for overflow
  3900 00001FA2 72D5                <1> 	jc	short dma_bnd_err
  3901                              <1> 	;
  3902 00001FA4 6629CA              <1> 	sub	dx, cx			; Restore start address
  3903                              <1> 	;
  3904 00001FA7 B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3905 00001FA9 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3906 00001FAA E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3907                              <1> 	IODELAY				; WAIT FOR I/O
  2103 00001FAC EB00                <2>  jmp short $+2
  2104 00001FAE EB00                <2>  jmp short $+2
  3908 00001FB0 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3909 00001FB2 89D0                <1> 	mov	eax,edx			; Buffer address
  3910 00001FB4 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3911                              <1> 	IODELAY				; WAIT FOR I/O
  2103 00001FB6 EB00                <2>  jmp short $+2
  2104 00001FB8 EB00                <2>  jmp short $+2
  3912 00001FBA 88E0                <1> 	MOV	AL,AH
  3913 00001FBC E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3914 00001FBE C1E810              <1> 	shr	eax,16
  3915                              <1> 	IODELAY				; I/O WAIT STATE
  2103 00001FC1 EB00                <2>  jmp short $+2
  2104 00001FC3 EB00                <2>  jmp short $+2
  3916 00001FC5 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3917                              <1> 	IODELAY
  2103 00001FC7 EB00                <2>  jmp short $+2
  2104 00001FC9 EB00                <2>  jmp short $+2
  3918 00001FCB 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3919 00001FCE E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3920                              <1> 	IODELAY				; WAIT FOR I/O
  2103 00001FD0 EB00                <2>  jmp short $+2
  2104 00001FD2 EB00                <2>  jmp short $+2
  3921 00001FD4 88E0                <1> 	MOV	AL,AH
  3922 00001FD6 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3923                              <1> 	IODELAY
  2103 00001FD8 EB00                <2>  jmp short $+2
  2104 00001FDA EB00                <2>  jmp short $+2
  3924 00001FDC FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3925 00001FDD B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3926 00001FDF E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3927 00001FE1 C3                  <1> 	retn
  3928                              <1> 
  3929                              <1> ;; 08/02/2015 - Protected Mode Modification
  3930                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3931                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3932                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3933                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3934                              <1> ;;	IODELAY
  3935                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3936                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3937                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3938                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3939                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3940                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3941                              <1> ;;	;JNC	short J33A
  3942                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3943                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3944                              <1> ;;;J33A:
  3945                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3946                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3947                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3948                              <1> ;;	IODELAY
  3949                              <1> ;;	MOV	AL,AH
  3950                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3951                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  3952                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3953                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3954                              <1> ;;	IODELAY
  3955                              <1> ;;	;AND	AL,00001111B
  3956                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3957                              <1> ;;
  3958                              <1> ;;;----- DETERMINE COUNT
  3959                              <1> ;;	sub	eax, eax ; 08/02/2015
  3960                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3961                              <1> ;;	CALL	GET_PARM		; "
  3962                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  3963                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  3964                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3965                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3966                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  3967                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3968                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3969                              <1> ;;	IODELAY
  3970                              <1> ;;	MOV	AL, AH
  3971                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3972                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3973                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  3974                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  3975                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3976                              <1> ;;	add	ecx, eax ; 08/02/2015
  3977                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3978                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3979                              <1> ;;	SIODELAY
  3980                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3981                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  3982                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  3983                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  3984                              <1> ;;	jz	short FMTDMA_OK
  3985                              <1> ;;	stc	; 20/02/2015
  3986                              <1> ;;fmtdma_bnd_err:
  3987                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3988                              <1> ;;FMTDMA_OK:
  3989                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3990                              <1> 
  3991                              <1> ;-------------------------------------------------------------------------------
  3992                              <1> ; NEC_INIT	
  3993                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3994                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3995                              <1> ;
  3996                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3997                              <1> ;
  3998                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3999                              <1> ;-------------------------------------------------------------------------------
  4000                              <1> NEC_INIT:
  4001                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  4002                              <1> 	; 24/12/2021
  4003 00001FE2 50                  <1> 	push	eax
  4004 00001FE3 E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  4005                              <1> 
  4006                              <1> ;-----	DO THE SEEK OPERATION
  4007                              <1> 
  4008 00001FE8 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  4009 00001FEB E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  4010                              <1> 	;POP	AX			; RECOVER COMMAND
  4011                              <1> 	; 24/12/2021
  4012 00001FF0 58                  <1> 	pop	eax
  4013 00001FF1 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  4014 00001FF3 BB[11200000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  4015 00001FF8 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  4016                              <1> 
  4017                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  4018                              <1> 
  4019 00001FF9 E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  4020 00001FFE 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  4021 00002001 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  4022 00002003 C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  4023 00002006 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  4024 00002009 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  4025 0000200B E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  4026 00002010 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  4027                              <1> ER_1:
  4028 00002011 C3                  <1> 	RETn
  4029                              <1> 
  4030                              <1> ;-------------------------------------------------------------------------------
  4031                              <1> ; RWV_COM
  4032                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  4033                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  4034                              <1> ;
  4035                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  4036                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4037                              <1> ;-------------------------------------------------------------------------------
  4038                              <1> RWV_COM:
  4039 00002012 B8[5D200000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  4040 00002017 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  4041 00002018 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  4042 0000201B E83E030000          <1> 	CALL	NEC_OUTPUT
  4043 00002020 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  4044 00002023 E836030000          <1> 	CALL	NEC_OUTPUT
  4045 00002028 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  4046 0000202B E82E030000          <1> 	CALL	NEC_OUTPUT
  4047 00002030 B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  4048 00002032 E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4049 00002037 E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4050 0000203C B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  4051 0000203E E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4052 00002043 E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4053 00002048 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  4054                              <1> _R15:
  4055 0000204B E80E030000          <1> 	CALL	NEC_OUTPUT
  4056 00002050 B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  4057 00002052 E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  4058 00002057 E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4059 0000205C 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4060                              <1> ER_2:
  4061 0000205D C3                  <1> 	RETn
  4062                              <1> 
  4063                              <1> ;-------------------------------------------------------------------------------
  4064                              <1> ; NEC_TERM
  4065                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4066                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4067                              <1> ;
  4068                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4069                              <1> ;-------------------------------------------------------------------------------
  4070                              <1> NEC_TERM:
  4071                              <1> 
  4072                              <1> ;-----	LET THE OPERATION HAPPEN
  4073                              <1> 
  4074 0000205E 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4075 0000205F E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4076 00002064 9C                  <1> 	PUSHFd	; 24/12/2021
  4077 00002065 E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4078 0000206A 724B                <1> 	JC	short SET_END_POP
  4079 0000206C 9D                  <1> 	POPFd	; 24/12/2021
  4080 0000206D 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4081                              <1> 
  4082                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4083                              <1> 
  4084 0000206F FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4085 00002070 BE[1D6D0000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4086 00002075 AC                  <1> 	lodsb				; GET ST0
  4087 00002076 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4088 00002078 7433                <1> 	JZ	short SET_END
  4089 0000207A 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4090 0000207C 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4091                              <1> 
  4092                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4093                              <1> 
  4094 0000207E AC                  <1> 	lodsb				; GET ST1
  4095 0000207F D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4096 00002081 B404                <1> 	MOV	AH,RECORD_NOT_FND
  4097 00002083 7222                <1> 	JC	short J19
  4098 00002085 C0E002              <1> 	SAL	AL,2
  4099 00002088 B410                <1> 	MOV	AH,BAD_CRC
  4100 0000208A 721B                <1> 	JC	short J19
  4101 0000208C D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4102 0000208E B408                <1> 	MOV	AH,BAD_DMA
  4103 00002090 7215                <1> 	JC	short J19
  4104 00002092 C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4105 00002095 B404                <1> 	MOV	AH,RECORD_NOT_FND
  4106 00002097 720E                <1> 	JC	short J19
  4107 00002099 D0E0                <1> 	SAL	AL,1
  4108 0000209B B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4109 0000209D 7208                <1> 	JC	short J19
  4110 0000209F D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4111 000020A1 B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4112 000020A3 7202                <1> 	JC	short J19
  4113                              <1> 
  4114                              <1> ;----- 	NEC MUST HAVE FAILED
  4115                              <1> J18:
  4116 000020A5 B420                <1> 	MOV	AH,BAD_NEC
  4117                              <1> J19:
  4118 000020A7 0825[1C6D0000]      <1> 	OR	[DSKETTE_STATUS],AH
  4119                              <1> SET_END:
  4120 000020AD 803D[1C6D0000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4121 000020B4 F5                  <1> 	CMC
  4122 000020B5 5E                  <1> 	POP	eSI
  4123 000020B6 C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4124                              <1> 
  4125                              <1> SET_END_POP:
  4126 000020B7 9D                  <1> 	POPFd	; 24/12/2021
  4127 000020B8 EBF3                <1> 	JMP	SHORT SET_END
  4128                              <1> 
  4129                              <1> ;-------------------------------------------------------------------------------
  4130                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4131                              <1> ;-------------------------------------------------------------------------------
  4132                              <1> DSTATE:
  4133 000020BA 803D[1C6D0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4134 000020C1 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4135 000020C3 808F[296D0000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4136 000020CA F687[296D0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4137 000020D1 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4138 000020D3 8A87[296D0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4139 000020D9 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4140 000020DB 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4141 000020DD 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4142                              <1> 
  4143                              <1> ;----- 	CHECK IF IT IS 1.44M
  4144                              <1> 
  4145 000020DF E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4146                              <1> 	;;20/02/2015
  4147                              <1> 	;;JC	short M_12		; CMOS BAD
  4148 000020E4 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4149 000020E6 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4150 000020E8 7410                <1> 	JE	short M_12		; YES
  4151                              <1> M_720:
  4152 000020EA 80A7[296D0000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4153 000020F1 808F[296D0000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4154 000020F8 EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4155                              <1> M_12:	
  4156 000020FA 808F[296D0000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4157                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4158                              <1> SETBAC:
  4159 00002101 C3                  <1> 	RETn
  4160                              <1> 
  4161                              <1> ;-------------------------------------------------------------------------------
  4162                              <1> ; RETRY	
  4163                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4164                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4165                              <1> ;
  4166                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4167                              <1> ;-------------------------------------------------------------------------------
  4168                              <1> RETRY:
  4169 00002102 803D[1C6D0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4170 00002109 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4171 0000210B 803D[1C6D0000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4172 00002112 743C                <1> 	JZ	short NO_RETRY
  4173 00002114 8AA7[296D0000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4174 0000211A F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4175 0000211D 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4176 0000211F 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4177 00002122 8A2D[246D0000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4178 00002128 C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4179 0000212B 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4180 0000212E 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4181 00002130 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4182                              <1> 
  4183                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4184                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4185                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4186                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4187                              <1> 
  4188 00002132 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4189 00002135 D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4190 00002137 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4191 0000213A 80A7[296D0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4192                              <1> 					; RATE, DBL STEP OFF
  4193 00002141 08A7[296D0000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4194 00002147 C605[1C6D0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4195 0000214E F9                  <1> 	STC				; SET CARRY FOR RETRY
  4196 0000214F C3                  <1> 	RETn				; RETRY RETURN
  4197                              <1> 
  4198                              <1> NO_RETRY:
  4199 00002150 F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4200 00002151 C3                  <1> 	RETn				; NO RETRY RETURN
  4201                              <1> 
  4202                              <1> ;-------------------------------------------------------------------------------
  4203                              <1> ; NUM_TRANS
  4204                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4205                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4206                              <1> ;
  4207                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4208                              <1> ;		SI-HI  = HEAD
  4209                              <1> ;		[BP]   = START SECTOR
  4210                              <1> ;
  4211                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4212                              <1> ;-------------------------------------------------------------------------------
  4213                              <1> NUM_TRANS:
  4214 00002152 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4215 00002154 803D[1C6D0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4216                              <1> 	; 24/12/2021
  4217 0000215B 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4218 0000215D B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4219 0000215F E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4220 00002164 8A1D[226D0000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4221 0000216A 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4222 0000216D 3A2D[216D0000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4223 00002173 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4224 00002175 8A2D[206D0000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4225 0000217B 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4226 0000217E 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4227 00002180 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4228                              <1> DIF_HD:
  4229 00002182 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4230                              <1> SAME_TRK:
  4231 00002184 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4232 00002187 88D8                <1> 	MOV	AL,BL			; TO AL
  4233                              <1> NT_OUT:
  4234 00002189 C3                  <1> 	RETn
  4235                              <1> 
  4236                              <1> ;-------------------------------------------------------------------------------
  4237                              <1> ; SETUP_END
  4238                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4239                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4240                              <1> ;
  4241                              <1> ; ON EXIT:
  4242                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4243                              <1> ;-------------------------------------------------------------------------------
  4244                              <1> SETUP_END:
  4245 0000218A B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4246                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4247 0000218C 50                  <1> 	push	eax ; 24/12/2021
  4248 0000218D E8C6000000          <1> 	CALL	GET_PARM
  4249 00002192 8825[1B6D0000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4250                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4251 00002198 58                  <1> 	pop	eax ; 24/12/2021
  4252 00002199 8A25[1C6D0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4253 0000219F 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4254 000021A1 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4255 000021A3 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4256                              <1> NUN_ERR: 
  4257 000021A5 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4258 000021A8 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4259 000021A9 C3                  <1> 	RETn
  4260                              <1> 
  4261                              <1> ;-------------------------------------------------------------------------------
  4262                              <1> ; SETUP_DBL
  4263                              <1> ;	CHECK DOUBLE STEP.
  4264                              <1> ;
  4265                              <1> ; ON ENTRY :	DI = DRIVE
  4266                              <1> ;
  4267                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4268                              <1> ;-------------------------------------------------------------------------------
  4269                              <1> SETUP_DBL:
  4270 000021AA 8AA7[296D0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4271 000021B0 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4272 000021B3 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4273                              <1> 
  4274                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4275                              <1> 
  4276 000021B5 C605[196D0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4277 000021BC E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4278 000021C1 B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4279 000021C3 E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4280 000021C8 E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4281 000021CD 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4282                              <1> 
  4283                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4284                              <1> 
  4285 000021CF 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4286 000021D3 F687[296D0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4287 000021DA 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4288 000021DC B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4289                              <1> 
  4290                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4291                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4292                              <1> ;	THEN SET DOUBLE STEP ON.
  4293                              <1> 
  4294                              <1> CNT_OK:
  4295 000021DE C605[1B6D0000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4296                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4297                              <1> 	; 24/12/2021
  4298 000021E5 51                  <1> 	push	ecx
  4299 000021E6 C605[1C6D0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4300 000021ED 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4301 000021F0 D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4302 000021F2 C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4303                              <1> 	;PUSH	AX			; SAVE HEAD
  4304                              <1> 	; 24/12/2021
  4305 000021F5 50                  <1> 	push	eax
  4306 000021F6 E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4307                              <1> 	;POP	AX			; RESTORE HEAD
  4308                              <1> 	; 24/12/2021
  4309 000021FB 58                  <1> 	pop	eax
  4310 000021FC 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4311 000021FF E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4312 00002204 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4313 00002205 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4314 0000220A 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4315                              <1> 	;POP	CX			; RESTORE COUNT
  4316                              <1> 	; 24/12/2021
  4317 0000220B 59                  <1> 	pop	ecx
  4318 0000220C 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4319 0000220E FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4320 00002210 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4321 00002212 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4322                              <1> 
  4323                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4324                              <1> 
  4325                              <1> SD_ERR:	
  4326 00002214 F9                  <1> 	STC				; SET CARRY FOR ERROR
  4327 00002215 C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4328                              <1> 
  4329                              <1> DO_CHK:
  4330 00002216 8A0D[206D0000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4331 0000221C 888F[2D6D0000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4332 00002222 D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4333 00002224 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4334 00002226 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4335 00002228 808F[296D0000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4336                              <1> NO_DBL:
  4337 0000222F F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4338 00002230 C3                  <1> 	RETn
  4339                              <1> 
  4340                              <1> ;-------------------------------------------------------------------------------
  4341                              <1> ; READ_ID
  4342                              <1> ;	READ ID FUNCTION.
  4343                              <1> ;
  4344                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4345                              <1> ;
  4346                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4347                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4348                              <1> ;-------------------------------------------------------------------------------
  4349                              <1> READ_ID:
  4350 00002231 B8[4E220000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4351 00002236 50                  <1> 	PUSH	eAX
  4352 00002237 B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4353 00002239 E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4354 0000223E 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4355 00002241 88C4                <1> 	MOV	AH,AL
  4356 00002243 E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4357 00002248 E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4358 0000224D 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4359                              <1> ER_3:
  4360 0000224E C3                  <1> 	RETn
  4361                              <1> 
  4362                              <1> ;-------------------------------------------------------------------------------
  4363                              <1> ; CMOS_TYPE
  4364                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4365                              <1> ;
  4366                              <1> ; ON ENTRY:	DI = DRIVE #
  4367                              <1> ;
  4368                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4369                              <1> ;-------------------------------------------------------------------------------
  4370                              <1> 
  4371                              <1> CMOS_TYPE: ; 11/12/2014
  4372 0000224F 8A87[8E670000]      <1> 	mov	al, [eDI+fd0_type]
  4373 00002255 20C0                <1> 	and 	al, al ; 18/12/2014
  4374 00002257 C3                  <1> 	retn
  4375                              <1> 
  4376                              <1> ;CMOS_TYPE:
  4377                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4378                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4379                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4380                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4381                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4382                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4383                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4384                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4385                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4386                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4387                              <1> ;TB:
  4388                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4389                              <1> ;BAD_CM:
  4390                              <1> ;	RETn				; CY, STATUS OF READ
  4391                              <1> 
  4392                              <1> ;-------------------------------------------------------------------------------
  4393                              <1> ; GET_PARM
  4394                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4395                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4396                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4397                              <1> ;	THE PARAMETER IN DL.
  4398                              <1> ;
  4399                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4400                              <1> ;
  4401                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4402                              <1> ;		AL,DH DESTROYED
  4403                              <1> ;-------------------------------------------------------------------------------
  4404                              <1> GET_PARM:
  4405                              <1> 	;PUSH	DS
  4406 00002258 56                  <1> 	PUSH	eSI
  4407                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4408                              <1>     	;MOV	DS,AX
  4409                              <1> 	;;mov	ax, cs
  4410                              <1> 	;;mov	ds, ax
  4411                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4412 00002259 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4413                              <1> 	;SUB	BH,BH			; BX = INDEX
  4414 0000225B 81E3FF000000        <1> 	and	ebx, 0FFh
  4415                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4416                              <1> 	;
  4417                              <1> 	; 17/12/2014
  4418 00002261 66A1[81670000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4419 00002267 38E0                <1> 	cmp	al, ah
  4420 00002269 7425                <1> 	je	short gpndc
  4421 0000226B A2[82670000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4422 00002270 53                  <1> 	push	ebx ; 08/02/2015
  4423 00002271 88C3                <1> 	mov	bl, al 
  4424                              <1> 	; 11/12/2014
  4425 00002273 8A83[8E670000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4426                              <1> 	; 18/12/2014
  4427 00002279 20C0                <1> 	and	al, al
  4428 0000227B 7507                <1> 	jnz	short gpdtc
  4429 0000227D BB[6B670000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4430 00002282 EB05                <1>         jmp     short gpdpu
  4431                              <1> gpdtc:	
  4432 00002284 E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4433                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4434                              <1> gpdpu:
  4435 00002289 891D[08670000]      <1> 	mov	[DISK_POINTER], ebx
  4436 0000228F 5B                  <1> 	pop	ebx
  4437                              <1> gpndc:
  4438 00002290 8B35[08670000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4439 00002296 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4440 00002299 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4441 0000229B 5E                  <1> 	POP	eSI
  4442                              <1> 	;POP	DS
  4443 0000229C C3                  <1> 	RETn
  4444                              <1> 
  4445                              <1> ;-------------------------------------------------------------------------------
  4446                              <1> ; MOTOR_ON
  4447                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4448                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4449                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4450                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4451                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4452                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4453                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4454                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4455                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4456                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4457                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4458                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4459                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4460                              <1> ;
  4461                              <1> ; ON ENTRY:	DI = DRIVE #
  4462                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4463                              <1> ;-------------------------------------------------------------------------------
  4464                              <1> MOTOR_ON:
  4465 0000229D 53                  <1> 	PUSH	eBX			; SAVE REG.
  4466 0000229E E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4467 000022A3 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4468 000022A5 E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4469 000022AA E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4470                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4471                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4472                              <1> M_WAIT:
  4473 000022AF B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4474 000022B1 E8A2FFFFFF          <1> 	CALL	GET_PARM
  4475                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4476                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4477                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4478 000022B6 80FC08              <1> 	cmp	ah, 8
  4479                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4480 000022B9 7702                <1> 	ja	short J13
  4481                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4482 000022BB B408                <1> 	mov	ah, 8
  4483                              <1> 
  4484                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4485                              <1> GP2:	
  4486                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4487                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4488 000022BD B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4489 000022C2 E80AF2FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4490                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4491 000022C7 FECC                <1> 	dec	ah
  4492 000022C9 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4493                              <1> MOT_IS_ON:
  4494 000022CB 5B                  <1> 	POP	eBX			; RESTORE REG.
  4495 000022CC C3                  <1> 	RETn
  4496                              <1> 
  4497                              <1> ;-------------------------------------------------------------------------------
  4498                              <1> ; TURN_ON
  4499                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4500                              <1> ;
  4501                              <1> ; ON ENTRY:	DI = DRIVE #
  4502                              <1> ;
  4503                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4504                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4505                              <1> ;		AX,BX,CX,DX DESTROYED
  4506                              <1> ;-------------------------------------------------------------------------------
  4507                              <1> TURN_ON:
  4508 000022CD 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4509 000022CF 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4510 000022D1 C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4511 000022D4 FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4512 000022D5 C605[1B6D0000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4513 000022DC A0[1A6D0000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4514 000022E1 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4515 000022E3 B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4516 000022E5 D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4517                              <1> 
  4518                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4519                              <1> ;  BL = DRIVE SELECT DESIRED
  4520                              <1> ;  AH = MOTOR ON MASK DESIRED
  4521                              <1> 
  4522 000022E7 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4523 000022E9 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4524 000022EB 8425[1A6D0000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4525 000022F1 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4526                              <1> 
  4527                              <1> TURN_IT_ON:
  4528 000022F3 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4529 000022F5 8A3D[1A6D0000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4530 000022FB 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4531 000022FE 8025[1A6D0000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4532 00002305 0825[1A6D0000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4533 0000230B A0[1A6D0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4534 00002310 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4535 00002312 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4536 00002315 FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4537 00002316 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4538 00002318 C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4539 0000231B 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4540 0000231D 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4541 00002321 EE                  <1> 	OUT	DX,AL
  4542 00002322 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4543                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4544 00002324 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4545 00002326 F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4546 00002327 C3                  <1> 	RETn
  4547                              <1> 
  4548                              <1> NO_MOT_WAIT:
  4549 00002328 FB                  <1> 	sti
  4550                              <1> no_mot_w1: ; 27/02/2015
  4551 00002329 F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4552                              <1> 	;STI				; INTERRUPTS BACK ON
  4553 0000232A C3                  <1> 	RETn
  4554                              <1> 
  4555                              <1> ;-------------------------------------------------------------------------------
  4556                              <1> ; HD_WAIT
  4557                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4558                              <1> ;
  4559                              <1> ; ON ENTRY:	DI = DRIVE #
  4560                              <1> ;
  4561                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4562                              <1> ;-------------------------------------------------------------------------------
  4563                              <1> HD_WAIT:
  4564 0000232B B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4565 0000232D E826FFFFFF          <1> 	CALL	GET_PARM
  4566 00002332 08E4                <1> 	or	ah, ah	; 17/12/2014
  4567 00002334 7519                <1> 	jnz	short DO_WAT
  4568 00002336 F605[1A6D0000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4569                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4570                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4571                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4572 0000233D 741E                <1> 	jz	short HW_DONE
  4573 0000233F B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4574 00002341 8A87[296D0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4575 00002347 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4576 00002349 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4577 0000234B 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4578                              <1> ;GP3:
  4579 0000234D B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4580                              <1> ;	JMP	SHORT DO_WAT
  4581                              <1> 
  4582                              <1> ;ISNT_WRITE:
  4583                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4584                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4585                              <1> 
  4586                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4587                              <1> DO_WAT:
  4588                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4589                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4590                              <1> J29:					; 	1 MILLISECOND LOOP
  4591                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4592 0000234F B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4593 00002354 E878F1FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4594                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4595 00002359 FECC                <1> 	dec	ah
  4596 0000235B 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4597                              <1> HW_DONE:
  4598 0000235D C3                  <1> 	RETn
  4599                              <1> 
  4600                              <1> ;-------------------------------------------------------------------------------
  4601                              <1> ; NEC_OUTPUT
  4602                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4603                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4604                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4605                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4606                              <1> ; 
  4607                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4608                              <1> ;
  4609                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4610                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4611                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4612                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4613                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4614                              <1> ;		AX,CX,DX DESTROYED
  4615                              <1> ;-------------------------------------------------------------------------------
  4616                              <1> 
  4617                              <1> ; 09/12/2014 [Erdogan Tan] 
  4618                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4619                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4620                              <1> ;	This read only register facilitates the transfer of data between
  4621                              <1> ;	the system microprocessor and the controller.
  4622                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4623                              <1> ;	  with the system micrprocessor.
  4624                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4625                              <1> ;	  the transfer is to the controller.
  4626                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4627                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4628                              <1> ; Bit 3 - Reserved.
  4629                              <1> ; Bit 2 - Reserved.
  4630                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4631                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4632                              <1> 
  4633                              <1> ; Data Register (3F5h)
  4634                              <1> ; This read/write register passes data, commands and parameters, and provides
  4635                              <1> ; diskette status information.
  4636                              <1>   		
  4637                              <1> NEC_OUTPUT:
  4638                              <1> 	;PUSH	BX			; SAVE REG.
  4639 0000235E 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4640                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4641                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4642                              <1> 	; 16/12/2014
  4643                              <1> 	; waiting for (max.) 0.5 seconds
  4644                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4645                              <1> 	;
  4646                              <1> 	; 17/12/2014
  4647                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4648                              <1> 	;
  4649                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4650                              <1> 	;		go on.
  4651                              <1> 	;INPUT:
  4652                              <1> 	;	AH=Mask for isolation bits.
  4653                              <1> 	;	AL=pattern to look for.
  4654                              <1> 	;	DX=Port to test for
  4655                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4656                              <1> 	;	     (normally 30 microseconds per period.)
  4657                              <1> 	;
  4658                              <1> 	;WFP_SHORT:  
  4659                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4660                              <1> 	;
  4661                              <1> 
  4662                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4663                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4664 00002362 B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4665                              <1> ;
  4666                              <1> ;WFPS_OUTER_LP:
  4667                              <1> ;	;
  4668                              <1> ;WFPS_CHECK_PORT:
  4669                              <1> J23:
  4670 00002367 EC                  <1> 	IN	AL,DX			; GET STATUS
  4671 00002368 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4672 0000236A 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4673 0000236C 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4674                              <1> WFPS_HI:
  4675 0000236E E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4676 00002370 A810                <1> 	TEST	AL,010H			; transition on memory
  4677 00002372 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4678                              <1> WFPS_LO:
  4679 00002374 E461                <1> 	IN	AL, PORT_B		; SYS1
  4680 00002376 A810                <1> 	TEST	AL,010H
  4681 00002378 74FA                <1> 	JZ	SHORT WFPS_LO
  4682                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4683 0000237A E2EB                <1> 	loop	J23	; 27/02/2015
  4684                              <1> ;	;
  4685                              <1> ;	dec	bl
  4686                              <1> ;	jnz	short WFPS_OUTER_LP
  4687                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4688                              <1> ;J23:
  4689                              <1> ;	IN	AL,DX			; GET STATUS
  4690                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4691                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4692                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4693                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4694                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4695                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4696                              <1>    
  4697                              <1> 	;;27/02/2015
  4698                              <1> 	;16/12/2014
  4699                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4700                              <1> 	;;jb	short J23
  4701                              <1> 
  4702                              <1> ;WFPS_TIMEOUT:
  4703                              <1> 
  4704                              <1> ;-----	FALL THRU TO ERROR RETURN
  4705                              <1> 
  4706 0000237C 800D[1C6D0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4707                              <1> 	;POP	BX			; RESTORE REG.
  4708 00002383 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4709 00002384 F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4710 00002385 C3                  <1> 	RETn
  4711                              <1> 
  4712                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4713                              <1> 
  4714                              <1> J27:	
  4715 00002386 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4716 00002388 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4717 0000238A EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4718                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4719                              <1> 	; 27/02/2015
  4720 0000238B 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE FLAGS
  4721                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4722 0000238C 29C9                <1> 	sub	ecx, ecx
  4723 0000238E B103                <1> 	mov	cl, 3 ; 24/12/2021
  4724 00002390 E83CF1FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4725 00002395 9D                  <1> 	POPFd	; 24/12/2021			; RESTORE FLAGS FOR EXIT
  4726                              <1> 	;POP	BX			; RESTORE REG
  4727 00002396 C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4728                              <1> 
  4729                              <1> ;-------------------------------------------------------------------------------
  4730                              <1> ; SEEK
  4731                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4732                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4733                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4734                              <1> ;
  4735                              <1> ; ON ENTRY:	DI = DRIVE #
  4736                              <1> ;		CH = TRACK #
  4737                              <1> ;
  4738                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4739                              <1> ;		AX,BX,CX DX DESTROYED
  4740                              <1> ;-------------------------------------------------------------------------------
  4741                              <1> SEEK:
  4742 00002397 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4743 00002399 B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4744 0000239B 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4745 0000239D D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4746 0000239F 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4747 000023A1 8405[196D0000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4748 000023A7 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4749                              <1> 
  4750 000023A9 0805[196D0000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4751 000023AF E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4752 000023B4 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4753                              <1> 
  4754                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4755                              <1> 
  4756 000023B6 C605[1C6D0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4757 000023BD E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4758 000023C2 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4759                              <1> 
  4760                              <1> AFT_RECAL:
  4761 000023C4 C687[2D6D0000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4762 000023CB 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4763 000023CD 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4764                              <1> 
  4765                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4766                              <1> 
  4767 000023CF F687[296D0000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4768 000023D6 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4769 000023D8 D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4770                              <1> 
  4771 000023DA 3AAF[2D6D0000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4772 000023E0 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4773                              <1> 
  4774 000023E2 BA[15240000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4775 000023E7 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4776 000023E8 88AF[2D6D0000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4777 000023EE B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4778 000023F0 E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4779 000023F5 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4780 000023F7 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4781 000023F9 E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4782 000023FE 8AA7[2D6D0000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4783 00002404 E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4784 00002409 E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4785                              <1> 
  4786                              <1> ;-----	WAIT FOR HEAD SETTLE
  4787                              <1> 
  4788                              <1> DO_WAIT:
  4789 0000240E 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE STATUS
  4790 0000240F E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4791 00002414 9D                  <1> 	POPFd	; 24/12/2021		; RESTORE STATUS
  4792                              <1> RB:
  4793                              <1> NEC_ERR:
  4794                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4795                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4796 00002415 C3                  <1> 	RETn				; RETURN TO CALLER
  4797                              <1> 
  4798                              <1> ;-------------------------------------------------------------------------------
  4799                              <1> ; RECAL
  4800                              <1> ;	RECALIBRATE DRIVE
  4801                              <1> ;
  4802                              <1> ; ON ENTRY:	DI = DRIVE #
  4803                              <1> ;
  4804                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4805                              <1> ;-------------------------------------------------------------------------------
  4806                              <1> RECAL:
  4807                              <1> 	;PUSH	CX
  4808                              <1> 	; 24/12/2021
  4809 00002416 51                  <1> 	push	ecx
  4810 00002417 B8[33240000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4811 0000241C 50                  <1> 	PUSH	eAX
  4812 0000241D B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4813 0000241F E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4814 00002424 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4815 00002426 88DC                <1> 	MOV	AH,BL
  4816 00002428 E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4817 0000242D E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4818 00002432 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4819                              <1> RC_BACK:
  4820                              <1> 	;POP	CX
  4821                              <1> 	; 24/12/2021
  4822 00002433 59                  <1> 	pop	ecx
  4823 00002434 C3                  <1> 	RETn
  4824                              <1> 
  4825                              <1> ;-------------------------------------------------------------------------------
  4826                              <1> ; CHK_STAT_2
  4827                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4828                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4829                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4830                              <1> ;
  4831                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4832                              <1> ;-------------------------------------------------------------------------------
  4833                              <1> CHK_STAT_2:
  4834 00002435 B8[5D240000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4835 0000243A 50                  <1> 	PUSH	eAX
  4836 0000243B E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4837 00002440 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4838 00002442 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4839 00002444 E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4840 00002449 E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4841 0000244E 720C                <1> 	JC	short J34
  4842 00002450 A0[1D6D0000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4843 00002455 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4844 00002457 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4845 00002459 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4846 0000245B F8                  <1> 	CLC				; GOOD RETURN
  4847                              <1> J34:
  4848 0000245C 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4849                              <1> CS_BACK:
  4850 0000245D C3                  <1> 	RETn
  4851                              <1> J35:
  4852 0000245E 800D[1C6D0000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4853 00002465 F9                  <1> 	STC				; ERROR RETURN CODE
  4854 00002466 EBF4                <1> 	JMP	SHORT J34
  4855                              <1> 
  4856                              <1> ;-------------------------------------------------------------------------------
  4857                              <1> ; WAIT_INT
  4858                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4859                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4860                              <1> ;	IF THE DRIVE IS NOT READY.
  4861                              <1> ;
  4862                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4863                              <1> ;-------------------------------------------------------------------------------
  4864                              <1> 
  4865                              <1> ; 17/12/2014
  4866                              <1> ; 2.5 seconds waiting !
  4867                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4868                              <1> ; amount of time to wait for completion interrupt from NEC.
  4869                              <1> 
  4870                              <1> 
  4871                              <1> WAIT_INT:
  4872 00002468 FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4873 00002469 F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4874                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4875                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4876                              <1> 
  4877                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4878                              <1> 	;
  4879                              <1> 	;WAIT_FOR_MEM:	
  4880                              <1> 	;	Waits for a bit at a specified memory location pointed
  4881                              <1> 	;	to by ES:[DI] to become set.
  4882                              <1> 	;INPUT:
  4883                              <1> 	;	AH=Mask to test with.
  4884                              <1> 	;	ES:[DI] = memory location to watch.
  4885                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4886                              <1> 	;	     (normally 30 microseconds per period.)
  4887                              <1> 
  4888                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4889                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4890                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4891                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4892                              <1> 	; 27/02/2015
  4893 0000246A B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4894                              <1> WFMS_CHECK_MEM:
  4895 0000246F F605[196D0000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4896 00002476 7516                <1>         jnz     short J37
  4897                              <1> WFMS_HI:
  4898 00002478 E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4899 0000247A A810                <1> 	TEST	AL,010H			; transition on memory
  4900 0000247C 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4901                              <1> WFMS_LO:
  4902 0000247E E461                <1> 	IN	AL,PORT_B		;SYS1
  4903 00002480 A810                <1> 	TEST	AL,010H
  4904 00002482 74FA                <1> 	JZ	SHORT WFMS_LO
  4905 00002484 E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4906                              <1> ;WFMS_OUTER_LP:
  4907                              <1> ;;	or	bl, bl			; check outer counter
  4908                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4909                              <1> ;	dec	bl
  4910                              <1> ;	jz	short J36A	
  4911                              <1> ;	jmp	short WFMS_CHECK_MEM
  4912                              <1> 
  4913                              <1> 	;17/12/2014
  4914                              <1> 	;16/12/2014
  4915                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4916                              <1> ;J36:
  4917                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4918                              <1> ;	JNZ	short J37
  4919                              <1> 	;16/12/2014
  4920                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4921                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4922                              <1> 	;JNZ	short J36
  4923                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4924                              <1> ;	jb	short J36
  4925                              <1> 
  4926                              <1> ;WFMS_TIMEOUT:
  4927                              <1> ;J36A:
  4928 00002486 800D[1C6D0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4929 0000248D F9                  <1> 	STC				; ERROR RETURN
  4930                              <1> J37:
  4931 0000248E 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4932 0000248F 8025[196D0000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4933 00002496 9D                  <1> 	POPF				; RECOVER CARRY
  4934 00002497 C3                  <1> 	RETn				; GOOD RETURN CODE
  4935                              <1> 
  4936                              <1> ;-------------------------------------------------------------------------------
  4937                              <1> ; RESULTS
  4938                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4939                              <1> ;	FOLLOWING AN INTERRUPT.
  4940                              <1> ;
  4941                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4942                              <1> ;		AX,BX,CX,DX DESTROYED
  4943                              <1> ;-------------------------------------------------------------------------------
  4944                              <1> RESULTS:
  4945 00002498 57                  <1> 	PUSH	eDI
  4946 00002499 BF[1D6D0000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4947 0000249E B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  4948 000024A0 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4949                              <1> 
  4950                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4951                              <1> 
  4952                              <1> _R10: 
  4953                              <1> 	; 16/12/2014
  4954                              <1> 	; wait for (max) 0.5 seconds
  4955                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  4956                              <1> 	;XOR	CX,CX			; COUNTER
  4957                              <1> 
  4958                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4959                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4960                              <1> 	; 27/02/2015
  4961 000024A4 B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4962                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4963                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4964                              <1> 
  4965                              <1> WFPSR_OUTER_LP:
  4966                              <1> 	;
  4967                              <1> WFPSR_CHECK_PORT:
  4968                              <1> J39:					; WAIT FOR MASTER
  4969 000024A9 EC                  <1> 	IN	AL,DX			; GET STATUS
  4970 000024AA 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4971 000024AC 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4972 000024AE 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  4973                              <1> WFPSR_HI:
  4974 000024B0 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4975 000024B2 A810                <1> 	TEST	AL,010H			; transition on memory
  4976 000024B4 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  4977                              <1> WFPSR_LO:
  4978 000024B6 E461                <1> 	IN	AL, PORT_B		; SYS1
  4979 000024B8 A810                <1> 	TEST	AL,010H
  4980 000024BA 74FA                <1> 	JZ	SHORT WFPSR_LO
  4981 000024BC E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  4982                              <1> 	;; 27/02/2015
  4983                              <1> 	;;dec	bh
  4984                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4985                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4986                              <1> 
  4987                              <1> 	;;mov	byte [wait_count], 0
  4988                              <1> ;J39:					; WAIT FOR MASTER
  4989                              <1> ;	IN	AL,DX			; GET STATUS
  4990                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4991                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4992                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  4993                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  4994                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  4995                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  4996                              <1> 	;
  4997                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  4998                              <1> 	;;jb	short J39	
  4999                              <1> 
  5000                              <1> ;WFPSR_TIMEOUT:
  5001 000024BE 800D[1C6D0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  5002 000024C5 F9                  <1> 	STC				; SET ERROR RETURN
  5003 000024C6 EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  5004                              <1> 
  5005                              <1> ;-----	READ IN THE STATUS
  5006                              <1> 
  5007                              <1> J42:
  5008 000024C8 EB00                <1> 	JMP	$+2			; I/O DELAY
  5009 000024CA 6642                <1> 	INC	DX			; POINT AT DATA PORT
  5010 000024CC EC                  <1> 	IN	AL,DX			; GET THE DATA
  5011                              <1> 	; 16/12/2014
  5012                              <1> 	NEWIODELAY
  2108 000024CD E6EB                <2>  out 0EBh,al
  5013 000024CF 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  5014 000024D1 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  5015                              <1> 	; 16/12/2014
  5016                              <1> ;	push	cx
  5017                              <1> ;	mov	cx, 30
  5018                              <1> ;wdw2:
  5019                              <1> ;	NEWIODELAY
  5020                              <1> ;	loop	wdw2
  5021                              <1> ;	pop	cx
  5022                              <1> 
  5023 000024D2 B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  5024 000024D7 E8F5EFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  5025 000024DC 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  5026 000024DE EC                  <1> 	IN	AL,DX			; GET STATUS
  5027                              <1> 	; 16/12/2014
  5028                              <1> 	NEWIODELAY
  2108 000024DF E6EB                <2>  out 0EBh,al
  5029                              <1> 	;
  5030 000024E1 A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  5031 000024E3 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  5032                              <1> 
  5033 000024E5 FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  5034 000024E7 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  5035 000024E9 800D[1C6D0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  5036 000024F0 F9                  <1> 	STC				; SET ERROR FLAG
  5037                              <1> 
  5038                              <1> ;-----	RESULT OPERATION IS DONE
  5039                              <1> POPRES:
  5040 000024F1 5F                  <1> 	POP	eDI
  5041 000024F2 C3                  <1> 	RETn				; RETURN WITH CARRY SET
  5042                              <1> 
  5043                              <1> ;-------------------------------------------------------------------------------
  5044                              <1> ; READ_DSKCHNG
  5045                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  5046                              <1> ;
  5047                              <1> ; ON ENTRY:	DI = DRIVE #
  5048                              <1> ;
  5049                              <1> ; ON EXIT:	DI = DRIVE #
  5050                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  5051                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  5052                              <1> ;		AX,CX,DX DESTROYED
  5053                              <1> ;-------------------------------------------------------------------------------
  5054                              <1> READ_DSKCHNG:
  5055 000024F3 E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  5056 000024F8 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  5057 000024FC EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  5058 000024FD A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5059 000024FF C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5060                              <1> 
  5061                              <1> ;-------------------------------------------------------------------------------
  5062                              <1> ; DRIVE_DET
  5063                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5064                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5065                              <1> ; ON ENTRY:	DI = DRIVE #
  5066                              <1> ;-------------------------------------------------------------------------------
  5067                              <1> DRIVE_DET:
  5068 00002500 E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5069 00002505 E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5070 0000250A 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5071 0000250C B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5072 0000250E E884FEFFFF          <1> 	CALL	SEEK
  5073 00002513 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5074 00002515 B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5075                              <1> SK_GIN:
  5076 00002517 FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5077                              <1> 	;PUSH	CX			; SAVE TRACK
  5078                              <1> 	; 24/12/2021
  5079 00002519 51                  <1> 	push	ecx
  5080 0000251A E878FEFFFF          <1> 	CALL	SEEK
  5081 0000251F 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5082 00002521 B8[5C250000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5083 00002526 50                  <1> 	PUSH	eAX
  5084 00002527 B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5085 00002529 E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5086 0000252E 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5087 00002531 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5088 00002533 E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5089 00002538 E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5090 0000253D 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5091                              <1> 	;POP	CX			; RESTORE TRACK
  5092                              <1> 	; 24/12/2021
  5093 0000253E 59                  <1> 	pop	ecx
  5094 0000253F F605[1D6D0000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5095 00002546 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5096 00002548 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5097 0000254A 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5098                              <1> 
  5099                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5100                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5101                              <1> 
  5102 0000254C 808F[296D0000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5103 00002553 C3                  <1> 	RETn				; ALL INFORMATION SET
  5104                              <1> IS_80:
  5105 00002554 808F[296D0000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5106                              <1> DD_BAC:
  5107 0000255B C3                  <1> 	RETn
  5108                              <1> POP_BAC:
  5109                              <1> 	;POP	CX			; THROW AWAY
  5110                              <1> 	; 24/12/2021
  5111 0000255C 59                  <1> 	pop	ecx
  5112 0000255D C3                  <1> 	RETn
  5113                              <1> 
  5114                              <1> fdc_int:  
  5115                              <1> 	  ; 30/07/2015	
  5116                              <1> 	  ; 16/02/2015
  5117                              <1> ;int_0Eh: ; 11/12/2014
  5118                              <1> 
  5119                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5120                              <1> ; DISK_INT
  5121                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5122                              <1> ;
  5123                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5124                              <1> ;-------------------------------------------------------------------------------
  5125                              <1> DISK_INT_1:
  5126                              <1> 
  5127                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5128                              <1> 	; 24/12/2021
  5129 0000255E 50                  <1> 	push	eax
  5130 0000255F 1E                  <1> 	push	ds
  5131 00002560 66B81000            <1> 	mov	ax, KDATA
  5132 00002564 8ED8                <1> 	mov 	ds, ax
  5133 00002566 800D[196D0000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5134 0000256D B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5135 0000256F E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5136 00002571 1F                  <1> 	pop	ds
  5137                              <1> 	;POP	AX			; RECOVER REGISTER
  5138                              <1> 	; 24/12/2021
  5139 00002572 58                  <1> 	pop	eax
  5140 00002573 CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5141                              <1> 
  5142                              <1> ;-------------------------------------------------------------------------------
  5143                              <1> ; DSKETTE_SETUP
  5144                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5145                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5146                              <1> ;-------------------------------------------------------------------------------
  5147                              <1> DSKETTE_SETUP:
  5148                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5149                              <1> 	;PUSH	BX
  5150                              <1> 	;PUSH	CX
  5151 00002574 52                  <1> 	PUSH	eDX
  5152                              <1> 	;PUSH	DI
  5153                              <1> 	;;PUSH	DS
  5154                              <1> 	; 14/12/2014
  5155                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5156                              <1> 	;mov	[DISK_POINTER+2], cs
  5157                              <1> 	;
  5158                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5159 00002575 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5160 00002577 66C705[296D0000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5160 0000257F 00                  <1>
  5161 00002580 8025[246D0000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5162 00002587 800D[246D0000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5163 0000258E C605[196D0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5164 00002595 C605[1B6D0000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5165 0000259C C605[1A6D0000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5166 000025A3 C605[1C6D0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5167                              <1> 	;
  5168                              <1> 	; 28/02/2015
  5169                              <1> 	;mov	word [cfd], 100h 
  5170 000025AA E89DF2FFFF          <1> 	call	DSK_RESET
  5171 000025AF 5A                  <1> 	pop	edx
  5172 000025B0 C3                  <1> 	retn
  5173                              <1> 
  5174                              <1> ;SUP0:
  5175                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5176                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5177                              <1> ;	; 02/01/2015
  5178                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5179                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5180                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5181                              <1> ;       cmp     byte [fd1_type], 0	
  5182                              <1> ;	jna	short sup1
  5183                              <1> ;	or	di, di
  5184                              <1> ;	jnz	short sup1
  5185                              <1> ;	inc	di
  5186                              <1> ;       jmp     short SUP0
  5187                              <1> ;sup1:
  5188                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5189                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5190                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5191                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5192                              <1> ;	;POP	DI
  5193                              <1> ;	POP	eDX
  5194                              <1> ;	;POP	CX
  5195                              <1> ;	;POP	BX
  5196                              <1> ;	;POP	AX
  5197                              <1> ;	RETn
  5198                              <1> 
  5199                              <1> ;//////////////////////////////////////////////////////
  5200                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5201                              <1> ;
  5202                              <1> 
  5203                              <1> int13h: ; 21/02/2015
  5204 000025B1 9C                  <1> 	pushfd
  5205 000025B2 0E                  <1> 	push 	cs
  5206 000025B3 E859000000          <1> 	call 	DISK_IO
  5207 000025B8 C3                  <1> 	retn
  5208                              <1> 
  5209                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5210                              <1> ;/////////////////////////////////////////////////////////////////////
  5211                              <1> 
  5212                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5213                              <1> ; 23/02/2015
  5214                              <1> ; 21/02/2015 (unix386.s)
  5215                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5216                              <1> ;
  5217                              <1> ; Original Source Code:
  5218                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5219                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5220                              <1> ;
  5221                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5222                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5223                              <1> ;
  5224                              <1> 
  5225                              <1> ;The wait for controller to be not busy is 10 seconds.
  5226                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5227                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5228                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5229                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5230                              <1> 
  5231                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5232                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5233                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5234                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5235                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5236                              <1> 
  5237                              <1> ;The wait for Data request on read and write longs is
  5238                              <1> ;2000 us. (?)
  5239                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5240                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5241                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5242                              <1> 
  5243                              <1> ; Port 61h (PORT_B)
  5244                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5245                              <1> 
  5246                              <1> ; 23/12/2014
  5247                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5248                              <1> 
  5249                              <1> ;--- INT 13H -------------------------------------------------------------------
  5250                              <1> ;									       :
  5251                              <1> ; FIXED DISK I/O INTERFACE						       :
  5252                              <1> ;									       :
  5253                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5254                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5255                              <1> ;									       :
  5256                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5257                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5258                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5259                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5260                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5261                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5262                              <1> ;									       :
  5263                              <1> ;------------------------------------------------------------------------------:
  5264                              <1> ;									       :
  5265                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5266                              <1> ;									       :
  5267                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5268                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5269                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5270                              <1> ;			  DL > 80H - DISK				       :
  5271                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5272                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5273                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5274                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5275                              <1> ;	(AH)= 06H  UNUSED						       :
  5276                              <1> ;	(AH)= 07H  UNUSED						       :
  5277                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5278                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5279                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5280                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5281                              <1> ;	(AH)= 0AH  READ LONG						       :
  5282                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5283                              <1> ;	(AH)= 0CH  SEEK 						       :
  5284                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5285                              <1> ;	(AH)= 0EH  UNUSED						       :
  5286                              <1> ;	(AH)= 0FH  UNUSED						       :
  5287                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5288                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5289                              <1> ;	(AH)= 12H  UNUSED						       :
  5290                              <1> ;	(AH)= 13H  UNUSED						       :
  5291                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5292                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5293                              <1> ;									       :
  5294                              <1> ;-------------------------------------------------------------------------------
  5295                              <1> ;									       :
  5296                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5297                              <1> ;									       :
  5298                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5299                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5300                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5301                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5302                              <1> ;									       :
  5303                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5304                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5305                              <1> ;				 (10 BITS TOTAL)			       :
  5306                              <1> ;									       :
  5307                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5308                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5309                              <1> ;									       :
  5310                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5311                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5312                              <1> ;									       :
  5313                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5314                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5315                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5316                              <1> ;			       80H FOR A BAD SECTOR			       :
  5317                              <1> ;			   N = SECTOR NUMBER				       :
  5318                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5319                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5320                              <1> ;									       :
  5321                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5322                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5323                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5324                              <1> ;									       :
  5325                              <1> ;-------------------------------------------------------------------------------
  5326                              <1> 
  5327                              <1> ;-------------------------------------------------------------------------------
  5328                              <1> ; OUTPUT								       :
  5329                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5330                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5331                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5332                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5333                              <1> ;									       :
  5334                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5335                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5336                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5337                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5338                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5339                              <1> ;		REWRITTEN.						       :
  5340                              <1> ;									       :
  5341                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5342                              <1> ;	   INPUT:							       :
  5343                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5344                              <1> ;	   OUTPUT:							       :
  5345                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5346                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5347                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5348                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5349                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5350                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5351                              <1> ;									       :
  5352                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5353                              <1> ;									       :
  5354                              <1> ;	AH = 0 - NOT PRESENT						       :
  5355                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5356                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5357                              <1> ;	     3 - FIXED DISK						       :
  5358                              <1> ;									       :
  5359                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5360                              <1> ;									       :
  5361                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5362                              <1> ;	INFORMATION.							       :
  5363                              <1> ;									       :
  5364                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5365                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5366                              <1> ;									       :
  5367                              <1> ;-------------------------------------------------------------------------------
  5368                              <1> 
  5369                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5370                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5371                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5372                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5373                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5374                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5375                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5376                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5377                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5378                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5379                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5380                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5381                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5382                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5383                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5384                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5385                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5386                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5387                              <1> 
  5388                              <1> ;--------------------------------------------------------
  5389                              <1> ;							:
  5390                              <1> ; FIXED DISK PARAMETER TABLE				:
  5391                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5392                              <1> ;							:
  5393                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5394                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5395                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5396                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5397                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5398                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5399                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5400                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5401                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5402                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5403                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5404                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5405                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5406                              <1> ;							:
  5407                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5408                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5409                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5410                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5411                              <1> ;							:
  5412                              <1> ;--------------------------------------------------------
  5413                              <1> 
  5414                              <1> ;--------------------------------------------------------
  5415                              <1> ;							:
  5416                              <1> ; HARDWARE SPECIFIC VALUES				:
  5417                              <1> ;							:
  5418                              <1> ;  -  CONTROLLER I/O PORT				:
  5419                              <1> ;							:
  5420                              <1> ;     > WHEN READ FROM: 				:
  5421                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5422                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5423                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5424                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5425                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5426                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5427                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5428                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5429                              <1> ;							:
  5430                              <1> ;     > WHEN WRITTEN TO:				:
  5431                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5432                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5433                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5434                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5435                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5436                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5437                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5438                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5439                              <1> ;							:
  5440                              <1> ;--------------------------------------------------------
  5441                              <1> 
  5442                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5443                              <1> ;HF1_PORT	equ	0170h	
  5444                              <1> ;HF_REG_PORT	EQU	03F6H
  5445                              <1> ;HF1_REG_PORT	equ	0376h
  5446                              <1> 
  5447                              <1> HDC1_BASEPORT	equ	1F0h
  5448                              <1> HDC2_BASEPORT	equ	170h		
  5449                              <1> 
  5450 000025B9 90                  <1> align 2
  5451                              <1> 
  5452                              <1> ;-----		STATUS REGISTER
  5453                              <1> 
  5454                              <1> ST_ERROR	EQU	00000001B	;
  5455                              <1> ST_INDEX	EQU	00000010B	;
  5456                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5457                              <1> ST_DRQ		EQU	00001000B	;
  5458                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5459                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5460                              <1> ST_READY	EQU	01000000B	;
  5461                              <1> ST_BUSY 	EQU	10000000B	;
  5462                              <1> 
  5463                              <1> ;-----		ERROR REGISTER
  5464                              <1> 
  5465                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5466                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5467                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5468                              <1> ;		EQU	00001000B	; NOT USED
  5469                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5470                              <1> ;		EQU	00100000B	; NOT USED
  5471                              <1> ERR_DATA_ECC	EQU	01000000B
  5472                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5473                              <1> 
  5474                              <1> 
  5475                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5476                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5477                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5478                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5479                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5480                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5481                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5482                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5483                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5484                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5485                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5486                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5487                              <1> 
  5488                              <1> ;MAX_FILE	EQU	2
  5489                              <1> ;S_MAX_FILE	EQU	2
  5490                              <1> MAX_FILE	equ	4		; 22/12/2014
  5491                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5492                              <1> 
  5493                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5494                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5495                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5496                              <1> 
  5497                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5498                              <1> 
  5499                              <1> ;-----		COMMAND BLOCK REFERENCE
  5500                              <1> 
  5501                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5502                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5503                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5504                              <1> ; 19/12/2014
  5505                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5506                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5507                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5508                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5509                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5510                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5511                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5512                              <1> 
  5513                              <1> align 2
  5514                              <1> 
  5515                              <1> ;----------------------------------------------------------------
  5516                              <1> ; FIXED DISK I/O SETUP						:
  5517                              <1> ;								:
  5518                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5519                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5520                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5521                              <1> ;								:
  5522                              <1> ;----------------------------------------------------------------
  5523                              <1> 
  5524                              <1> DISK_SETUP:
  5525                              <1> 	;CLI
  5526                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5527                              <1> 	;xor	ax,ax
  5528                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5529                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5530                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5531                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5532                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5533                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5534                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5535                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5536                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5537                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5538                              <1> 	;;MOV	[HDISK_INT+2],CS
  5539                              <1> 	;mov	[HDISK_INT1+2],CS
  5540                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5541                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5542                              <1> 	;mov	[HDISK_INT2+2],CS
  5543                              <1> 	;
  5544                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5545                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5546                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5547                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5548                              <1> 	;push	cs
  5549                              <1> 	;pop	ds
  5550                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5551                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5552 000025BA C705[346D0000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5552 000025C2 0900                <1>
  5553                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5554                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5555 000025C4 C705[386D0000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5555 000025CC 0900                <1>
  5556                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5557                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5558 000025CE C705[3C6D0000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5558 000025D6 0900                <1>
  5559                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5560                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5561 000025D8 C705[406D0000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5561 000025E0 0900                <1>
  5562                              <1> 	;
  5563                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5564                              <1> 	;;;AND	AL,0BFH
  5565                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5566                              <1> 	;;;JMP	$+2
  5567                              <1> 	;;IODELAY
  5568                              <1> 	;;OUT	INTB01,AL
  5569                              <1> 	;;IODELAY
  5570                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5571                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5572                              <1> 	;;;JMP	$+2
  5573                              <1> 	;;IODELAY
  5574                              <1> 	;;OUT	INTA01,AL
  5575                              <1> 	;
  5576                              <1> 	;STI
  5577                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5578                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5579                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5580                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5581                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5582                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5583                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5584                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5585                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5586                              <1> 	;mov	si, hd0_type
  5587 000025E2 BE[90670000]        <1> 	mov	esi, hd0_type
  5588                              <1> 	;mov	cx, 4
  5589 000025E7 B904000000          <1> 	mov	ecx, 4
  5590                              <1> hde_l:
  5591 000025EC AC                  <1> 	lodsb
  5592 000025ED 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5593 000025EF 7206                <1> 	jb	short _L4
  5594 000025F1 FE05[306D0000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5595                              <1> _L4: ; 26/02/2015
  5596 000025F7 E2F3                <1> 	loop	hde_l	
  5597                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5598                              <1> ;L4:
  5599                              <1> 	; 
  5600                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5601                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5602                              <1> 	;;mov 	cl, 3
  5603                              <1> 	;;
  5604                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5605                              <1> ;;hdc_dl:
  5606                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5607                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5608                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5609                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5610                              <1> 	;;jnc	short hdc_reset0
  5611                              <1> 	;;loop	hdc_dl
  5612                              <1> 	;;; 27/12/2014
  5613                              <1> 	;;stc
  5614                              <1> 	;;retn
  5615                              <1> 	;
  5616                              <1> ;;hdc_reset0:
  5617                              <1> 	; 18/01/2015
  5618 000025F9 8A0D[306D0000]      <1> 	mov	cl, [HF_NUM]
  5619 000025FF 20C9                <1> 	and	cl, cl
  5620 00002601 740D                <1> 	jz	short POD_DONE
  5621                              <1> 	;
  5622 00002603 B27F                <1> 	mov	dl, 7Fh
  5623                              <1> hdc_reset1:
  5624 00002605 FEC2                <1> 	inc	dl
  5625                              <1> 	;; 31/12/2015
  5626                              <1> 	;;push	dx
  5627                              <1> 	;;push	cx
  5628                              <1> 	;;push	ds
  5629                              <1> 	;;sub	ax, ax
  5630                              <1> 	;;mov	ds, ax
  5631                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5632                              <1> 	;;pop	ds
  5633                              <1> 	;;MOV	BX,AX
  5634                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5635                              <1> 	;;MOV	CX,AX
  5636                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5637                              <1> 	;;
  5638                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5639                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5640                              <1> 	;;pop	cx
  5641                              <1> 	;;pop	dx
  5642                              <1> 	;;
  5643                              <1> 	; 18/01/2015
  5644 00002607 B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5645                              <1> 	;int	13h
  5646 00002609 E8A3FFFFFF          <1> 	call	int13h
  5647 0000260E E2F5                <1> 	loop	hdc_reset1
  5648                              <1> POD_DONE:
  5649 00002610 C3                  <1> 	RETn
  5650                              <1> 
  5651                              <1> ;;-----	POD_ERROR
  5652                              <1> 
  5653                              <1> ;;CTL_ERRX:
  5654                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5655                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5656                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5657                              <1> ;	;JMP	short POD_DONE
  5658                              <1> 
  5659                              <1> ;;HD_RESET_1:
  5660                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5661                              <1> ;;	;PUSH	CX
  5662                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5663                              <1> ;;	INT	13H
  5664                              <1> ;;	JC	short RES_2
  5665                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5666                              <1> ;;	INT	13H
  5667                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5668                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5669                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5670                              <1> ;;					; (30 seconds)		
  5671                              <1> ;;	;cmc
  5672                              <1> ;;	;JNC	short RES_1
  5673                              <1> ;;	jb	short RES_1
  5674                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5675                              <1> ;;	;TEST	DL,1
  5676                              <1> ;;	;JNZ	RES_E1
  5677                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5678                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5679                              <1> ;;	;JMP	SHORT RES_E1
  5680                              <1> ;;RES_ER: ; 22/12/2014
  5681                              <1> ;;RES_OK:
  5682                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5683                              <1> ;;	;POP	BX
  5684                              <1> ;;	RETn
  5685                              <1> ;;
  5686                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5687                              <1> ;;	INT	13H
  5688                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5689                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5690                              <1> ;;	INT	13H
  5691                              <1> ;;	JC	short RES_ER
  5692                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5693                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5694                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5695                              <1> ;;	INT	13H
  5696                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5697                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5698                              <1> ;;	JE	short RES_OK
  5699                              <1> ;;	CMP	AH,DATA_CORRECTED
  5700                              <1> ;;	JE	short RES_OK
  5701                              <1> ;;	CMP	AH,BAD_ECC
  5702                              <1> ;;	JE	short RES_OK
  5703                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5704                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5705                              <1> ;;					; (60 seconds)		
  5706                              <1> ;;	cmc
  5707                              <1> ;;	JC	short RES_ER		; FAILED
  5708                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5709                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5710                              <1> ;;	AND	AL,3FH
  5711                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5712                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5713                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5714                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5715                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5716                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5717                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5718                              <1> ;;	;TEST	DL,1
  5719                              <1> ;;	;JNZ	short RES_E1
  5720                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5721                              <1> ;;;RES_E1:
  5722                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5723                              <1> ;;;RES_OK:
  5724                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5725                              <1> ;;	;POP	BX
  5726                              <1> ;;	;RETn
  5727                              <1> ;
  5728                              <1> ;;SET_FAIL:
  5729                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5730                              <1> ;	;CALL	CMOS_READ
  5731                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5732                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5733                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5734                              <1> ;	;RETn
  5735                              <1> ;
  5736                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5737                              <1> ;	;POP	AX			; SAVE RETURN
  5738                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5739                              <1> ;	;POP	BX
  5740                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5741                              <1> ;	;PUSH	CX
  5742                              <1> ;	;PUSH	AX
  5743                              <1> ;	;push	ds
  5744                              <1> ;	;xor	ax, ax
  5745                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5746                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5747                              <1> ;	;				; BX = START TIME
  5748                              <1> ;	;				; CX = END TIME
  5749                              <1> ;	;pop	ds
  5750                              <1> ;	;CMP	BX,CX
  5751                              <1> ;	;JB	short TCHK1		; START < END
  5752                              <1> ;	;CMP	BX,AX
  5753                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5754                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5755                              <1> ;;TCHK1: CMP	AX,BX
  5756                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5757                              <1> ;;TCHK2: CMP	AX,CX
  5758                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5759                              <1> ;;					; OR CURRENT < END < START
  5760                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5761                              <1> ;;	RETn
  5762                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5763                              <1> ;;	RETn
  5764                              <1> ;;
  5765                              <1> ;;int_13h:
  5766                              <1> 
  5767                              <1> ;----------------------------------------
  5768                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5769                              <1> ;----------------------------------------
  5770                              <1> 
  5771                              <1> DISK_IO:
  5772 00002611 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5773                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5774                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5775                              <1> 	;;call	int40h
  5776                              <1> 	;jb	DISKETTE_IO_1
  5777                              <1> 	; 24/12/2021
  5778 00002614 7305                <1> 	jnb	short A1
  5779 00002616 E95FF1FFFF          <1> 	jmp	DISKETTE_IO_1
  5780                              <1> ;RET_2:
  5781                              <1> 	;RETf	2			; BACK TO CALLER
  5782                              <1> ;	retf	4
  5783                              <1> A1:
  5784 0000261B FB                  <1> 	STI				; ENABLE INTERRUPTS
  5785                              <1> 	;; 04/01/2015
  5786                              <1> 	;;OR	AH,AH
  5787                              <1> 	;;JNZ	short A2
  5788                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5789                              <1> 	;;SUB	AH,AH
  5790 0000261C 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5791 0000261F 772E                <1> 	JA	short RET_2
  5792                              <1> 	; 18/01/2015
  5793 00002621 08E4                <1> 	or	ah,ah
  5794 00002623 742D                <1> 	jz	short A4
  5795 00002625 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5796 00002628 7504                <1> 	jne	short A2
  5797 0000262A 28E4                <1> 	sub	ah,ah	; Reset
  5798 0000262C EB24                <1> 	jmp	short A4
  5799                              <1> A2:
  5800 0000262E 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5801                              <1> 	;JNZ	short A3
  5802                              <1>         ;JMP    GET_PARM_N
  5803                              <1> 	;je	GET_PARM_N
  5804                              <1> 	; 24/12/2021
  5805 00002631 7505                <1> 	jne	short A3
  5806 00002633 E90D030000          <1> 	jmp	GET_PARM_N
  5807                              <1> A3:	
  5808 00002638 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5809                              <1> 	;JNZ	short A4
  5810                              <1>         ;JMP    READ_DASD_TYPE
  5811                              <1> 	;je	READ_DASD_TYPE
  5812                              <1> 	; 24/12/2021
  5813 0000263B 7505                <1> 	jne	short A3_A4
  5814 0000263D E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5815                              <1> A3_A4:
  5816                              <1> 	; 02/02/2015
  5817 00002642 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5818                              <1> 	; 12/01/2015
  5819 00002645 F5                  <1> 	cmc
  5820 00002646 730A                <1> 	jnc	short A4
  5821                              <1> 	; 30/01/2015
  5822                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5823 00002648 C605[2F6D0000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5824                              <1> 	;jmp	short RET_2
  5825                              <1> RET_2:
  5826 0000264F CA0400              <1> 	retf	4
  5827                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5828 00002652 C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5829 00002656 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5830 00002657 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5831 00002658 52                  <1> 	PUSH	eDX
  5832 00002659 1E                  <1> 	PUSH	DS
  5833 0000265A 06                  <1> 	PUSH	ES
  5834 0000265B 56                  <1> 	PUSH	eSI
  5835 0000265C 57                  <1> 	PUSH	eDI
  5836                              <1> 	;;04/01/2015
  5837                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5838                              <1> 	;;JNZ	short A5
  5839                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5840                              <1> ;;A5:	
  5841                              <1> 	;push	cs
  5842                              <1> 	;pop	ds
  5843                              <1> 	; 21/02/2015
  5844                              <1> 	;push	ax
  5845                              <1> 	; 24/12/2021
  5846 0000265D 50                  <1> 	push	eax
  5847 0000265E 66B81000            <1> 	mov	ax, KDATA
  5848 00002662 8ED8                <1> 	mov	ds, ax
  5849 00002664 8EC0                <1> 	mov	es, ax	
  5850                              <1> 	;pop	ax
  5851                              <1> 	; 24/12/2021
  5852 00002666 58                  <1> 	pop	eax
  5853 00002667 E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5854                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5855 0000266C 8A25[2F6D0000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5856 00002672 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5857 00002675 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5858 00002676 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5859 00002677 5E                  <1> 	POP	eSI
  5860 00002678 07                  <1>         POP     ES
  5861 00002679 1F                  <1>         POP     DS
  5862 0000267A 5A                  <1> 	POP	eDX
  5863 0000267B 59                  <1> 	POP	eCX
  5864 0000267C 5B                  <1> 	POP	eBX
  5865 0000267D C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5866                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5867 0000267E CA0400              <1> 	retf	4
  5868                              <1> ; 21/02/2015
  5869                              <1> ;       dw --> dd
  5870                              <1> M1:					; FUNCTION TRANSFER TABLE
  5871 00002681 [3A280000]          <1> 	dd	DISK_RESET		; 000H
  5872 00002685 [AF280000]          <1> 	dd	RETURN_STATUS		; 001H
  5873 00002689 [BC280000]          <1> 	dd	DISK_READ		; 002H
  5874 0000268D [C5280000]          <1> 	dd	DISK_WRITE		; 003H
  5875 00002691 [CE280000]          <1> 	dd	DISK_VERF		; 004H
  5876 00002695 [E6280000]          <1> 	dd	FMT_TRK 		; 005H
  5877 00002699 [30280000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5878 0000269D [30280000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5879 000026A1 [30280000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5880 000026A5 [A7290000]          <1> 	dd	INIT_DRV		; 009H
  5881 000026A9 [062A0000]          <1> 	dd	RD_LONG 		; 00AH
  5882 000026AD [0F2A0000]          <1> 	dd	WR_LONG 		; 00BH
  5883 000026B1 [182A0000]          <1> 	dd	DISK_SEEK		; 00CH
  5884 000026B5 [3A280000]          <1> 	dd	DISK_RESET		; 00DH
  5885 000026B9 [30280000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5886 000026BD [30280000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5887 000026C1 [402A0000]          <1> 	dd	TST_RDY 		; 010H
  5888 000026C5 [642A0000]          <1> 	dd	HDISK_RECAL		; 011H
  5889 000026C9 [30280000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5890 000026CD [30280000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5891 000026D1 [9A2A0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5892                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5893 000026D5 [30280000]          <1> 	dd	BAD_COMMAND		; 015h
  5894 000026D9 [30280000]          <1> 	dd	BAD_COMMAND		; 016h
  5895 000026DD [30280000]          <1> 	dd	BAD_COMMAND		; 017h
  5896 000026E1 [30280000]          <1> 	dd	BAD_COMMAND		; 018h
  5897 000026E5 [30280000]          <1> 	dd	BAD_COMMAND		; 019h
  5898 000026E9 [30280000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5899 000026ED [BC280000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5900 000026F1 [C5280000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5901                              <1> M1L     EQU    $-M1
  5902                              <1> 
  5903                              <1> DISK_IO_CONT:
  5904                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5905 000026F5 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5906                              <1> 	;;JNZ	short SU0
  5907                              <1>         ;;JMP	RETURN_STATUS
  5908                              <1> 	;je	RETURN_STATUS
  5909                              <1> 	; 24/12/2021
  5910 000026F8 7505                <1> 	jne	short SU0
  5911 000026FA E9B0010000          <1> 	jmp	RETURN_STATUS
  5912                              <1> SU0:
  5913 000026FF C605[2F6D0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5914                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5915                              <1> 	;mov	si, bx ;; 14/02/2015
  5916 00002706 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5917 00002708 8A1D[306D0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5918                              <1> 	;; 04/01/2015
  5919                              <1> 	;;PUSH	AX
  5920 0000270E 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5921                              <1> 					; (get drive number as 0 to 3)
  5922 00002711 38D3                <1> 	CMP	BL,DL
  5923                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5924                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5925                              <1> 	; 24/12/2021
  5926 00002713 7705                <1> 	ja	short su0_su1
  5927 00002715 E916010000          <1> 	jmp	BAD_COMMAND
  5928                              <1> su0_su1:
  5929                              <1>         ;;03/01/2015
  5930 0000271A 29DB                <1> 	sub	ebx, ebx
  5931 0000271C 88D3                <1> 	mov	bl, dl
  5932                              <1> 	;sub	bh, bh
  5933 0000271E 883D[446D0000]      <1> 	mov	[LBAMode], bh 	; 0
  5934                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5935                              <1> 	;test	byte [ebx+hd0_type], 1
  5936                              <1> 	;jz	short su1		; no
  5937                              <1> 	;inc	byte [LBAMode]
  5938                              <1> ;su1:
  5939                              <1> 	; 21/02/2015 (32 bit modification)
  5940                              <1> 	; 04/01/2015
  5941                              <1> 	;push	ax ; ***
  5942                              <1> 	; 24/12/2021
  5943 00002724 50                  <1> 	push	eax ; ***
  5944                              <1> 	;PUSH	ES ; **
  5945                              <1> 	;PUSH	DX ; *
  5946                              <1> 	; 24/12/2021
  5947 00002725 52                  <1> 	push	edx ; *
  5948                              <1> 	;push	ax
  5949 00002726 50                  <1> 	push	eax
  5950 00002727 E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5951                              <1> 	; 02/02/2015
  5952                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  5953 0000272C 668B4310            <1> 	mov	ax, [ebx+16]
  5954 00002730 66A3[84670000]      <1> 	mov	[HF_PORT], ax
  5955                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  5956 00002736 668B5312            <1> 	mov	dx, [ebx+18]
  5957 0000273A 668915[86670000]    <1> 	mov	[HF_REG_PORT], dx
  5958                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  5959 00002741 8A4314              <1> 	mov	al, [ebx+20]
  5960                              <1> 	; 23/02/2015
  5961 00002744 A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5962 00002746 7406                <1> 	jz 	short su1
  5963 00002748 FE05[446D0000]      <1> 	inc	byte [LBAMode] ; 1 
  5964                              <1> su1: 	 
  5965 0000274E C0E804              <1> 	shr 	al, 4
  5966 00002751 2401                <1> 	and	al, 1			
  5967 00002753 A2[88670000]        <1> 	mov	[hf_m_s], al 
  5968                              <1> 	;
  5969                              <1> 	; 03/01/2015
  5970                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  5971 00002758 8A4308              <1> 	mov	al, [ebx+8]
  5972                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  5973 0000275B EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  5974                              <1> 					; Control Byte:  (= 08h, here)
  5975                              <1> 					; bit 0 - 0
  5976                              <1> 					; bit 1 - nIEN (1 = disable irq)
  5977                              <1> 					; bit 2 - SRST (software RESET)
  5978                              <1> 					; bit 3 - use extra heads (8 to 15)
  5979                              <1> 					;         -always set to 1-	
  5980                              <1> 					; (bits 3 to 7 are reserved
  5981                              <1> 					;          for ATA devices)
  5982 0000275C 8A25[316D0000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5983 00002762 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  5984 00002765 08C4                <1> 	OR	AH,AL
  5985 00002767 8825[316D0000]      <1> 	MOV	[CONTROL_BYTE],AH	
  5986                              <1> 	; 04/01/2015
  5987                              <1> 	;pop	ax
  5988                              <1> 	; 24/12/2021
  5989 0000276D 58                  <1> 	pop	eax
  5990                              <1> 	;pop	dx ; * ;; 14/02/2015
  5991                              <1> 	; 24/12/2021
  5992 0000276E 5A                  <1> 	pop	edx ; *
  5993 0000276F 20E4                <1> 	and	ah, ah	; Reset function ?
  5994 00002771 7506                <1> 	jnz	short su2
  5995                              <1> 	;;pop	dx ; * ;; 14/02/2015
  5996                              <1> 	;pop	es ; **
  5997                              <1> 	;pop	ax ; ***
  5998                              <1> 	; 24/12/2021
  5999 00002773 58                  <1> 	pop	eax ; ***	
  6000                              <1> 	;;pop	bx
  6001 00002774 E9C1000000          <1>         jmp     DISK_RESET
  6002                              <1> su2:
  6003 00002779 803D[446D0000]00    <1> 	cmp	byte [LBAMode], 0
  6004 00002780 765E                <1> 	jna	short su3
  6005                              <1> 	;
  6006                              <1> 	; 02/02/2015 (LBA read/write function calls)
  6007 00002782 80FC1B              <1> 	cmp	ah, 1Bh
  6008 00002785 720B                <1> 	jb	short lbarw1
  6009 00002787 80FC1C              <1> 	cmp	ah, 1Ch
  6010 0000278A 7759                <1> 	ja 	short invldfnc
  6011                              <1> 	;;pop	dx ; * ; 14/02/2015
  6012                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  6013 0000278C 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  6014                              <1> 	;; 14/02/2015
  6015 0000278E 88D1                <1> 	mov	cl, dl ; 14/02/2015
  6016                              <1> 	;;mov	dx, bx
  6017                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  6018                              <1> 	;;mov	bx, di
  6019                              <1> 	;mov	si, di ; Buffer offset
  6020 00002790 EB2E                <1> 	jmp	short lbarw2
  6021                              <1> lbarw1:
  6022                              <1> 	; convert CHS to LBA
  6023                              <1> 	;
  6024                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  6025                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  6026                              <1> 	;	+ Sector - 1
  6027                              <1> 	;push	dx ; * ;; 14/02/2015
  6028                              <1> 	; 24/12/2021
  6029 00002792 52                  <1> 	push	edx ; *
  6030                              <1> 	;xor	dh, dh
  6031 00002793 31D2                <1> 	xor	edx, edx
  6032                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  6033 00002795 8A530E              <1> 	mov	dl, [ebx+14]
  6034                              <1> 	;xor	ah, ah
  6035 00002798 31C0                <1> 	xor	eax, eax
  6036                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  6037 0000279A 8A4302              <1> 	mov	al, [ebx+2]
  6038 0000279D FEC8                <1> 	dec	al
  6039                              <1> 	;inc	ax		; 0 =  256
  6040 0000279F 40                  <1> 	inc	eax ; 24/12/2021
  6041 000027A0 66F7E2              <1> 	mul 	dx
  6042                              <1> 		; AX = # of Heads" * Sectors/Track
  6043 000027A3 6689CA              <1> 	mov	dx, cx
  6044                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  6045 000027A6 83E13F              <1> 	and	ecx, 3fh
  6046 000027A9 86D6                <1> 	xchg	dl, dh
  6047 000027AB C0EE06              <1> 	shr	dh, 6
  6048                              <1> 		; DX = cylinder (0 to 1023)
  6049                              <1> 	;mul 	dx
  6050                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  6051 000027AE F7E2                <1> 	mul	edx
  6052 000027B0 FEC9                <1> 	dec	cl  ; sector - 1
  6053                              <1> 	;add	ax, cx
  6054                              <1> 	;adc	dx, 0
  6055                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  6056 000027B2 01C8                <1> 	add	eax, ecx
  6057                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  6058                              <1> 	; 24/12/2021
  6059 000027B4 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6060                              <1> 	;push	dx
  6061                              <1> 	;push	ax
  6062 000027B5 50                  <1> 	push	eax
  6063                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6064 000027B6 8A430E              <1> 	mov	al, [ebx+14]
  6065 000027B9 F6E5                <1> 	mul	ch
  6066                              <1> 		; AX = Head * Sectors/Track
  6067 000027BB 6699                <1>         cwd
  6068                              <1> 	;pop	dx
  6069 000027BD 5A                  <1> 	pop	edx
  6070                              <1> 	;add	ax, dx
  6071                              <1> 	;pop	dx
  6072                              <1> 	;adc	dx, 0 ; add carry bit
  6073 000027BE 01D0                <1> 	add	eax, edx
  6074                              <1> lbarw2:
  6075 000027C0 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6076 000027C2 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6077 000027C4 C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6078                              <1> 				; NOTE: Features register (1F1h, 171h)
  6079                              <1> 				; is not used for ATA device R/W functions. 
  6080                              <1> 				; It is old/obsolete 'write precompensation'
  6081                              <1> 				; register and error register
  6082                              <1> 				; for old ATA/IDE devices.
  6083                              <1> 	; 18/01/2014
  6084                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6085 000027C8 8A0D[88670000]      <1> 	mov	cl, [hf_m_s]
  6086                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6087                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6088                              <1> 				; bit 6 = 1 = LBA mode
  6089                              <1> 				; bit 7 = 1
  6090 000027CE 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6091                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6092 000027D1 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6093 000027D6 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6094                              <1> 	;or	dh, ch
  6095 000027D9 09C8                <1> 	or	eax, ecx	
  6096                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6097                              <1> 				  ; (Sector Number Register)
  6098                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6099                              <1> 				  ; (Cylinder Low Register)
  6100                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6101                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6102                              <1> 				  ; (Cylinder High Register)
  6103                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6104                              <1> 				  ; (Drive/Head Register)
  6105                              <1> 	
  6106                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6107 000027DB 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6108                              <1> 	;14/02/2015
  6109                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6110 000027DE EB37                <1> 	jmp	short su4
  6111                              <1> su3:
  6112                              <1> 	; 02/02/2015 
  6113                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6114 000027E0 80FC14              <1> 	cmp 	ah, 14h
  6115 000027E3 7603                <1> 	jna 	short chsfnc
  6116                              <1> invldfnc:
  6117                              <1>         ; 14/02/2015  
  6118                              <1> 	;pop	es ; **
  6119                              <1>         ;pop	ax ; ***
  6120                              <1>         ; 24/12/2021
  6121 000027E5 58                  <1> 	pop	eax ; ***
  6122                              <1> 	;jmp	short BAD_COMMAND_POP
  6123 000027E6 EB48                <1>         jmp     short BAD_COMMAND
  6124                              <1> chsfnc:	
  6125                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6126 000027E8 668B4305            <1> 	mov	ax, [ebx+5]
  6127 000027EC 66C1E802            <1> 	SHR	AX,2
  6128 000027F0 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6129                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6130                              <1> 	;;PUSH	DX
  6131                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6132                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6133                              <1> 	;;POP	DX ; * 
  6134                              <1> 	;;POP	ES ; **
  6135                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6136                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6137                              <1> 	;;OR	AH,AL
  6138                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6139                              <1> 	;
  6140 000027F3 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6141 000027F5 243F                <1> 	AND	AL,3FH
  6142 000027F7 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6143 000027FA 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6144 000027FD 88C8                <1> 	MOV	AL,CL
  6145 000027FF C0E806              <1> 	SHR	AL,6
  6146 00002802 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6147                              <1> 	;;05/01/2015
  6148                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6149 00002805 A0[88670000]        <1> 	mov	al, [hf_m_s]
  6150 0000280A C0E004              <1> 	SHL	AL,4
  6151 0000280D 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6152 00002810 08F0                <1> 	OR	AL,DH
  6153                              <1> 	;OR	AL,80H or 20H
  6154 00002812 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6155 00002814 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6156                              <1> su4:
  6157                              <1> 	;POP	ES ; **
  6158                              <1>         ;; 14/02/2015
  6159                              <1>         ;;POP   AX
  6160                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6161                              <1>         ;;PUSH  AX
  6162                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6163                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6164                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6165                              <1> 	;pop     ax ; ***
  6166                              <1> 	; 24/12/2021
  6167 00002817 58                  <1> 	pop	eax ; ***
  6168 00002818 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6169 0000281B 29DB                <1>         sub	ebx, ebx
  6170 0000281D 88E3                <1> 	mov     bl, ah
  6171                              <1>         ;xor	bh, bh
  6172                              <1>         ;sal	bx, 1
  6173 0000281F 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6174                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6175                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6176                              <1>         ;;JNB   short BAD_COMMAND_POP
  6177                              <1>         ;cmp	bx, M1L
  6178 00002823 83FB74              <1> 	cmp	ebx, M1L
  6179 00002826 7308                <1> 	jnb	short BAD_COMMAND
  6180                              <1>         ;xchg	bx, si
  6181 00002828 87DE                <1>         xchg	ebx, esi
  6182                              <1> 	;;;POP	AX			; RESTORE AX
  6183                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6184                              <1> 	
  6185                              <1> 	;;PUSH	CX
  6186                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6187                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6188                              <1> 	;SHR	CX,4
  6189                              <1> 	;MOV	AX,ES
  6190                              <1> 	;ADD	AX,CX
  6191                              <1> 	;MOV	ES,AX
  6192                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6193                              <1> 	;;POP	AX
  6194                              <1> 	;;POP	CX
  6195                              <1> 	;;JMP	word [CS:SI+M1]
  6196                              <1> 	;jmp	word [SI+M1]
  6197 0000282A FFA6[81260000]      <1> 	jmp	dword [esi+M1]
  6198                              <1> ;;BAD_COMMAND_POP:
  6199                              <1> ;;	POP	AX
  6200                              <1> ;;	POP	BX
  6201                              <1> BAD_COMMAND:
  6202 00002830 C605[2F6D0000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6203 00002837 B000                <1> 	MOV	AL,0
  6204 00002839 C3                  <1> 	RETn
  6205                              <1> 
  6206                              <1> ;----------------------------------------
  6207                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6208                              <1> ;----------------------------------------
  6209                              <1> 
  6210                              <1> ; 18-1-2015 : one controller reset (not other one)
  6211                              <1> 
  6212                              <1> DISK_RESET:
  6213 0000283A FA                  <1> 	CLI
  6214 0000283B E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6215                              <1> 	;JMP	$+2
  6216                              <1> 	IODELAY
  2103 0000283D EB00                <2>  jmp short $+2
  2104 0000283F EB00                <2>  jmp short $+2
  6217                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6218 00002841 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6219 00002843 E6A1                <1> 	OUT	INTB01,AL
  6220 00002845 FB                  <1> 	STI				; START INTERRUPTS
  6221                              <1> 	; 14/02/2015
  6222                              <1> 	;mov	di, dx
  6223                              <1> 	; 24/12/2021
  6224 00002846 89D7                <1> 	mov	edi, edx	
  6225                              <1> 	; 04/01/2015
  6226                              <1> 	;xor	di,di
  6227                              <1> drst0:
  6228 00002848 B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6229                              <1> 	;MOV	DX,HF_REG_PORT
  6230 0000284A 668B15[86670000]    <1> 	MOV	DX,[HF_REG_PORT]
  6231 00002851 EE                  <1> 	OUT	DX,AL			; RESET
  6232                              <1> ;	MOV	CX,10			; DELAY COUNT
  6233                              <1> ;DRD:	DEC	CX
  6234                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6235                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6236 00002852 B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6237 00002857 E875ECFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6238                              <1>                                         ; 40 micro seconds)
  6239 0000285C A0[316D0000]        <1> 	mov	al,[CONTROL_BYTE]
  6240 00002861 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6241 00002863 EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6242 00002864 E807040000          <1> 	CALL	NOT_BUSY
  6243 00002869 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6244 0000286B 668B15[84670000]    <1> 	MOV	DX,[HF_PORT]
  6245 00002872 FEC2                <1> 	inc	dl  ; HF_PORT+1
  6246                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6247                              <1>         ;mov	cl, 10
  6248 00002874 B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6249                              <1> drst1:
  6250 00002879 EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6251 0000287A 3C01                <1> 	CMP	AL,1
  6252                              <1> 	; 04/01/2015
  6253 0000287C 740A                <1> 	jz	short drst2
  6254                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6255                              <1>         	; Drive/Head Register - bit 4
  6256 0000287E E2F9                <1> 	loop	drst1
  6257                              <1> DRERR:	
  6258 00002880 C605[2F6D0000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6259 00002887 C3                  <1> 	RETn
  6260                              <1> drst2:
  6261                              <1> 	; 14/02/2015
  6262                              <1> 	;mov	dx, di
  6263                              <1> 	; 24/12/2021
  6264 00002888 89FA                <1> 	mov	edx, edi
  6265                              <1> ;drst3:
  6266                              <1> ;	; 05/01/2015
  6267                              <1> ;	shl 	di,1
  6268                              <1> ;	; 04/01/2015
  6269                              <1> ;	mov	ax,[di+hd_cports]
  6270                              <1> ;	cmp	ax,[HF_REG_PORT]
  6271                              <1> ;	je	short drst4
  6272                              <1> ;	mov	[HF_REG_PORT], ax
  6273                              <1> ;	; 03/01/2015
  6274                              <1> ;	mov	ax,[di+hd_ports]
  6275                              <1> ;       mov     [HF_PORT], ax
  6276                              <1> ;	; 05/01/2014
  6277                              <1> ;	shr	di,1
  6278                              <1> ;	; 04/01/2015
  6279                              <1> ;	jmp	short drst0	; reset other controller
  6280                              <1> ;drst4:
  6281                              <1> ;	; 05/01/2015
  6282                              <1> ;	shr	di,1
  6283                              <1> ;	mov	al,[di+hd_dregs]
  6284                              <1> ;	and	al,10h ; bit 4 only
  6285                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6286                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6287                              <1> 	;
  6288 0000288A A0[88670000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6289 0000288F A801                <1> 	test	al,1
  6290                              <1> ;	jnz	short drst6
  6291 00002891 7516                <1>         jnz     short drst4
  6292 00002893 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6293                              <1> ;drst5:
  6294                              <1> drst3:
  6295 00002897 E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6296                              <1> 	;mov	dx,di
  6297 0000289C E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6298                              <1> 	; 04/01/2014
  6299                              <1> ;	inc	di
  6300                              <1> ;	mov	dx,di
  6301                              <1> ;	cmp	dl,[HF_NUM]
  6302                              <1> ;	jb	short drst3
  6303                              <1> ;DRE:
  6304 000028A1 C605[2F6D0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6305 000028A8 C3                  <1> 	RETn
  6306                              <1> ;drst6:
  6307                              <1> drst4:		; Drive/Head Register - bit 4
  6308 000028A9 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6309                              <1>         ;jmp    short drst5
  6310 000028AD EBE8                <1>         jmp     short drst3
  6311                              <1> 
  6312                              <1> ;----------------------------------------
  6313                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6314                              <1> ;----------------------------------------
  6315                              <1> 
  6316                              <1> RETURN_STATUS:
  6317 000028AF A0[2F6D0000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6318 000028B4 C605[2F6D0000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6319 000028BB C3                  <1> 	RETn
  6320                              <1> 
  6321                              <1> ;----------------------------------------
  6322                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6323                              <1> ;----------------------------------------
  6324                              <1> 
  6325                              <1> DISK_READ:
  6326 000028BC C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6327 000028C0 E92A020000          <1>         JMP     COMMANDI
  6328                              <1> 
  6329                              <1> ;----------------------------------------
  6330                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6331                              <1> ;----------------------------------------
  6332                              <1> 
  6333                              <1> DISK_WRITE:
  6334 000028C5 C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6335 000028C9 E976020000          <1>         JMP     COMMANDO
  6336                              <1> 
  6337                              <1> ;----------------------------------------
  6338                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6339                              <1> ;----------------------------------------
  6340                              <1> 
  6341                              <1> DISK_VERF:
  6342 000028CE C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6343 000028D2 E8E4020000          <1> 	CALL	COMMAND
  6344 000028D7 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6345 000028D9 E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6346 000028DE 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6347 000028E0 E8E3030000          <1> 	CALL	CHECK_STATUS
  6348                              <1> VERF_EXIT:
  6349 000028E5 C3                  <1> 	RETn
  6350                              <1> 
  6351                              <1> ;----------------------------------------
  6352                              <1> ;	FORMATTING	     (AH = 05H) :
  6353                              <1> ;----------------------------------------
  6354                              <1> 
  6355                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6356 000028E6 C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6357                              <1> 	;PUSH	ES
  6358                              <1> 	;PUSH	BX
  6359 000028EA 53                  <1> 	push	ebx
  6360 000028EB E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6361                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6362 000028F0 8A430E              <1> 	mov	al, [ebx+14]
  6363 000028F3 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6364 000028F6 5B                  <1> 	pop	ebx
  6365                              <1> 	;POP	BX
  6366                              <1> 	;POP	ES
  6367 000028F7 E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6368                              <1> 
  6369                              <1> ;----------------------------------------
  6370                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6371                              <1> ;----------------------------------------
  6372                              <1> 
  6373                              <1> READ_DASD_TYPE:
  6374                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6375 000028FC 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6376                              <1> 	;PUSH	ES
  6377 000028FD 53                  <1> 	PUSH	eBX
  6378                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6379                              <1> 	;push	cs
  6380                              <1> 	;pop	ds
  6381 000028FE 66BB1000            <1>         mov	bx, KDATA
  6382 00002902 8EDB                <1> 	mov	ds, bx
  6383                              <1> 	;mov	es, bx
  6384 00002904 C605[2F6D0000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6385 0000290B 8A1D[306D0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6386 00002911 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6387 00002914 38D3                <1> 	CMP	BL,DL
  6388 00002916 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6389 00002918 E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6390                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6391 0000291D 8A4302              <1> 	mov	al, [ebx+2]
  6392                              <1> 	;MOV	CL,[ES:BX+14]
  6393 00002920 8A4B0E              <1> 	mov	cl, [ebx+14]
  6394 00002923 F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6395                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6396 00002925 668B0B              <1> 	mov	cx, [ebx]
  6397                              <1> 	;
  6398                              <1> 	; 02/01/2015 
  6399                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6400                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6401 00002928 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6402                              <1> 	;
  6403 0000292A 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6404 0000292D 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6405 00002930 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6406                              <1> 	;SUB	AX,AX
  6407 00002933 28C0                <1> 	sub	al, al
  6408 00002935 B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6409 00002937 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6410                              <1> 	;POP	ES
  6411 00002938 1F                  <1> 	POP	DS
  6412 00002939 F8                  <1> 	CLC				; CLEAR CARRY
  6413                              <1> 	;RETf	2
  6414 0000293A CA0400              <1> 	retf	4
  6415                              <1> RDT_NOT_PRESENT:
  6416                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6417                              <1> 	; 24/12/2021
  6418 0000293D 29C0                <1> 	sub	eax, eax
  6419                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6420                              <1> 	;MOV	DX,AX
  6421 0000293F 89C1                <1> 	mov	ecx, eax
  6422 00002941 89C2                <1> 	mov	edx, eax
  6423 00002943 EBF2                <1> 	JMP	short RDT2
  6424                              <1> 
  6425                              <1> ;----------------------------------------
  6426                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6427                              <1> ;----------------------------------------
  6428                              <1> 
  6429                              <1> GET_PARM_N:
  6430                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6431 00002945 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6432                              <1> 	;PUSH	ES
  6433 00002946 53                  <1> 	PUSH	eBX
  6434                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6435                              <1> 	;MOV	DS,AX
  6436                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6437                              <1> 	;JZ	short G0
  6438                              <1> 	;LES	BX,@HF1_TBL_VEC
  6439                              <1> 	;JMP	SHORT G1
  6440                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6441                              <1> ;G1:
  6442                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6443                              <1> 	; 22/12/2014
  6444                              <1> 	;push	cs
  6445                              <1> 	;pop	ds
  6446 00002947 66BB1000            <1> 	mov	bx, KDATA
  6447 0000294B 8EDB                <1> 	mov	ds, bx
  6448                              <1> 	;mov	es, bx
  6449                              <1> 	;
  6450 0000294D 80EA80              <1> 	SUB	DL,80H
  6451 00002950 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6452 00002953 7340                <1> 	JAE	short G4
  6453                              <1> 	;
  6454 00002955 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6455                              <1> 	; 22/12/2014
  6456 00002957 88D3                <1> 	mov	bl, dl
  6457                              <1> 	;xor	bh, bh  
  6458 00002959 C0E302              <1> 	shl	bl, 2			; convert index to offset
  6459                              <1> 	;add	bx, HF_TBL_VEC
  6460 0000295C 81C3[346D0000]      <1> 	add	ebx, HF_TBL_VEC
  6461                              <1> 	;mov	ax, [bx+2]
  6462                              <1> 	;mov	es, ax			; dpt segment
  6463                              <1> 	;mov	bx, [bx]		; dpt offset
  6464 00002962 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6465                              <1> 
  6466 00002964 C605[2F6D0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6467                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6468 0000296B 668B03              <1> 	mov	ax, [ebx]
  6469                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6470 0000296E 6648                <1> 	dec	ax			; max. cylinder number
  6471 00002970 88C5                <1> 	MOV	CH,AL
  6472 00002972 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6473 00002976 66D1E8              <1> 	SHR	AX,1
  6474 00002979 66D1E8              <1> 	SHR	AX,1
  6475                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6476 0000297C 0A430E              <1> 	or	al, [ebx+14]
  6477 0000297F 88C1                <1> 	MOV	CL,AL
  6478                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6479 00002981 8A7302              <1> 	mov	dh, [ebx+2]
  6480 00002984 FECE                <1> 	DEC	DH			; 0-N RANGE
  6481 00002986 8A15[306D0000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6482                              <1> 	;SUB	AX,AX
  6483                              <1> 	; 24/12/2021
  6484 0000298C 29C0                <1> 	sub	eax, eax
  6485                              <1> 	; 27/12/2014 
  6486                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6487                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6488                              <1> 	;mov	di, bx			; HDPT offset
  6489 0000298E 89DF                <1> 	mov	edi, ebx
  6490                              <1> G5:
  6491 00002990 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6492                              <1> 	;POP	ES
  6493 00002991 1F                  <1> 	POP	DS
  6494                              <1> 	;RETf	2
  6495 00002992 CA0400              <1> 	retf	4
  6496                              <1> G4:
  6497 00002995 C605[2F6D0000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6498                              <1> 	; 24/12/2021
  6499 0000299C 29C0                <1> 	sub	eax, eax
  6500 0000299E B407                <1> 	MOV	AH,INIT_FAIL
  6501                              <1> 	;SUB	AL,AL
  6502                              <1> 	;SUB	DX,DX
  6503 000029A0 29D2                <1> 	sub	edx, edx
  6504                              <1> 	;SUB	CX,CX
  6505 000029A2 29C9                <1> 	sub	ecx, ecx
  6506 000029A4 F9                  <1> 	STC				; SET ERROR FLAG
  6507 000029A5 EBE9                <1> 	JMP	short G5
  6508                              <1> 
  6509                              <1> ;----------------------------------------
  6510                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6511                              <1> ;----------------------------------------
  6512                              <1> 	; 03/01/2015
  6513                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6514                              <1> 	; logical sector per logical track
  6515                              <1> 	; and logical heads - 1 would be set but
  6516                              <1> 	; it is seen as it will be good
  6517                              <1> 	; if physical parameters will be set here
  6518                              <1> 	; because, number of heads <= 16.
  6519                              <1> 	; (logical heads usually more than 16)
  6520                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6521                              <1> 	;	== INT 13h physical parameters
  6522                              <1> 
  6523                              <1> ;INIT_DRV:
  6524                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6525                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6526                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6527                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6528                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6529                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6530                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6531                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6532                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6533                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6534                              <1> ;	SUB	AX,AX
  6535                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6536                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6537                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6538                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6539                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6540                              <1> ;	CALL	CHECK_STATUS
  6541                              <1> ;INIT_EXIT:
  6542                              <1> ;	RETn
  6543                              <1> 
  6544                              <1> ; 04/01/2015
  6545                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6546                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6547                              <1> INIT_DRV:
  6548                              <1> 	;xor	ah,ah
  6549 000029A7 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6550 000029A9 B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6551 000029AB 3825[446D0000]      <1>         cmp     [LBAMode], ah   ; 0
  6552 000029B1 7702                <1> 	ja	short idrv0
  6553 000029B3 B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6554                              <1> idrv0:
  6555                              <1> 	; DL = drive number (0 based)
  6556 000029B5 E8BB030000          <1> 	call	GET_VEC
  6557                              <1> 	;push	bx
  6558 000029BA 53                  <1> 	push	ebx ; 21/02/2015
  6559                              <1> 	;add	bx,ax
  6560 000029BB 01C3                <1> 	add	ebx,eax
  6561                              <1> 	;; 05/01/2015
  6562 000029BD 8A25[88670000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6563                              <1> 	;;and 	ah,1 
  6564 000029C3 C0E404              <1> 	shl	ah,4
  6565 000029C6 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6566                              <1> 	;mov	al,[es:bx]
  6567 000029C9 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6568 000029CB FEC8                <1> 	dec	al	 ; last head number 
  6569                              <1> 	;and	al,0Fh
  6570 000029CD 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6571                              <1> 	;
  6572 000029CF C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6573 000029D3 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6574                              <1> 	;pop	bx
  6575 000029D6 5B                  <1> 	pop	ebx
  6576 000029D7 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6577 000029D9 B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6578 000029DB 803D[446D0000]00    <1> 	cmp	byte [LBAMode],0
  6579 000029E2 7702                <1> 	ja	short idrv1
  6580 000029E4 B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6581                              <1> idrv1:
  6582                              <1> 	;xor	ah,ah
  6583                              <1> 	;add	bx,ax
  6584 000029E6 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6585                              <1> 	;mov	al,[es:bx]
  6586                              <1> 			; sector number
  6587 000029E8 8A03                <1> 	mov	al,[ebx]
  6588 000029EA 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6589 000029ED 28C0                <1> 	sub	al,al
  6590 000029EF 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6591 000029F2 E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6592 000029F7 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6593 000029F9 E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6594 000029FE 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6595 00002A00 E8C3020000          <1> 	call	CHECK_STATUS
  6596                              <1> INIT_EXIT:
  6597 00002A05 C3                  <1> 	RETn
  6598                              <1> 
  6599                              <1> ;----------------------------------------
  6600                              <1> ;	READ LONG	     (AH = 0AH) :
  6601                              <1> ;----------------------------------------
  6602                              <1> 
  6603                              <1> RD_LONG:
  6604                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6605 00002A06 C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6606 00002A0A E9E0000000          <1>         JMP     COMMANDI
  6607                              <1> 
  6608                              <1> ;----------------------------------------
  6609                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6610                              <1> ;----------------------------------------
  6611                              <1> 
  6612                              <1> WR_LONG:
  6613                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6614 00002A0F C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6615 00002A13 E92C010000          <1>         JMP     COMMANDO
  6616                              <1> 
  6617                              <1> ;----------------------------------------
  6618                              <1> ;	SEEK		     (AH = 0CH) :
  6619                              <1> ;----------------------------------------
  6620                              <1> 
  6621                              <1> DISK_SEEK:
  6622 00002A18 C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6623 00002A1C E89A010000          <1> 	CALL	COMMAND
  6624 00002A21 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6625 00002A23 E80C020000          <1> 	CALL	_WAIT
  6626 00002A28 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6627 00002A2A E899020000          <1> 	CALL	CHECK_STATUS
  6628 00002A2F 803D[2F6D0000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6629 00002A36 7507                <1> 	JNE	short DS_EXIT
  6630 00002A38 C605[2F6D0000]00    <1>         MOV     byte [DISK_STATUS1],0
  6631                              <1> DS_EXIT:
  6632 00002A3F C3                  <1> 	RETn
  6633                              <1> 
  6634                              <1> ;----------------------------------------
  6635                              <1> ;	TEST DISK READY      (AH = 10H) :
  6636                              <1> ;----------------------------------------
  6637                              <1> 
  6638                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6639 00002A40 E82B020000          <1> 	CALL	NOT_BUSY
  6640 00002A45 751C                <1> 	JNZ	short TR_EX
  6641 00002A47 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6642 00002A4A 668B15[84670000]    <1> 	MOV	DX,[HF_PORT]
  6643 00002A51 80C206              <1> 	add	dl,6
  6644 00002A54 EE                  <1> 	OUT	DX,AL
  6645 00002A55 E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6646 00002A5A 7507                <1> 	JNZ	short TR_EX
  6647 00002A5C C605[2F6D0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6648                              <1> TR_EX:	
  6649 00002A63 C3                  <1> 	RETn
  6650                              <1> 
  6651                              <1> ;----------------------------------------
  6652                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6653                              <1> ;----------------------------------------
  6654                              <1> 
  6655                              <1> HDISK_RECAL:
  6656 00002A64 C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6657 00002A68 E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6658 00002A6D 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6659 00002A6F E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6660 00002A74 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6661 00002A76 E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6662 00002A7B 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6663                              <1> RECAL_X:
  6664 00002A7D E846020000          <1> 	CALL	CHECK_STATUS
  6665 00002A82 803D[2F6D0000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6666 00002A89 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6667 00002A8B C605[2F6D0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6668                              <1> RECAL_EXIT:
  6669 00002A92 803D[2F6D0000]00    <1>         CMP     byte [DISK_STATUS1],0
  6670 00002A99 C3                  <1> 	RETn
  6671                              <1> 
  6672                              <1> ;----------------------------------------
  6673                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6674                              <1> ;----------------------------------------
  6675                              <1> 
  6676                              <1> CTLR_DIAGNOSTIC:
  6677 00002A9A FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6678 00002A9B E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6679                              <1> 	;AND	AL,0BFH
  6680 00002A9D 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6681                              <1> 	;JMP	$+2
  6682                              <1> 	IODELAY
  2103 00002A9F EB00                <2>  jmp short $+2
  2104 00002AA1 EB00                <2>  jmp short $+2
  6683 00002AA3 E6A1                <1> 	OUT	INTB01,AL
  6684                              <1> 	IODELAY
  2103 00002AA5 EB00                <2>  jmp short $+2
  2104 00002AA7 EB00                <2>  jmp short $+2
  6685 00002AA9 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6686 00002AAB 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6687                              <1> 	;JMP	$+2
  6688                              <1> 	IODELAY
  2103 00002AAD EB00                <2>  jmp short $+2
  2104 00002AAF EB00                <2>  jmp short $+2
  6689 00002AB1 E621                <1> 	OUT	INTA01,AL
  6690 00002AB3 FB                  <1> 	STI
  6691 00002AB4 E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6692 00002AB9 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6693                              <1> 	;MOV	DX, HF_PORT+7
  6694 00002ABB 668B15[84670000]    <1> 	mov	dx, [HF_PORT]
  6695 00002AC2 80C207              <1> 	add	dl, 7
  6696 00002AC5 B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6697 00002AC7 EE                  <1> 	OUT	DX,AL
  6698 00002AC8 E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6699 00002ACD B480                <1> 	MOV	AH,TIME_OUT
  6700 00002ACF 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6701                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6702 00002AD1 668B15[84670000]    <1> 	mov	dx, [HF_PORT]
  6703 00002AD8 FEC2                <1> 	inc	dl
  6704 00002ADA EC                  <1> 	IN	AL,DX
  6705 00002ADB A2[266D0000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6706 00002AE0 B400                <1> 	MOV	AH,0
  6707 00002AE2 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6708 00002AE4 7402                <1> 	JE	SHORT CD_EXIT
  6709 00002AE6 B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6710                              <1> CD_EXIT:
  6711 00002AE8 8825[2F6D0000]      <1> 	MOV	[DISK_STATUS1],AH
  6712 00002AEE C3                  <1> 	RETn
  6713                              <1> 
  6714                              <1> ;----------------------------------------
  6715                              <1> ; COMMANDI				:
  6716                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6717                              <1> ;	NSECTOR RETURNS ZERO		:
  6718                              <1> ;----------------------------------------
  6719                              <1> COMMANDI:
  6720 00002AEF E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6721 00002AF4 724D                <1> 	JC	short CMD_ABORT
  6722                              <1> 	;MOV	DI,BX
  6723 00002AF6 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6724 00002AF8 E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6725 00002AFD 7544                <1> 	JNZ	short CMD_ABORT
  6726                              <1> CMD_I1:
  6727 00002AFF E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6728 00002B04 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6729                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6730 00002B06 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6731                              <1> 	;MOV	DX,HF_PORT
  6732 00002B0B 668B15[84670000]    <1> 	mov	dx,[HF_PORT]
  6733 00002B12 FA                  <1> 	CLI
  6734 00002B13 FC                  <1> 	CLD
  6735 00002B14 F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6736 00002B17 FB                  <1> 	STI
  6737 00002B18 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6738 00002B1C 7419                <1> 	JZ	CMD_I3
  6739 00002B1E E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6740 00002B23 721E                <1> 	JC	short TM_OUT
  6741                              <1> 	;MOV	DX,HF_PORT
  6742 00002B25 668B15[84670000]    <1> 	mov	dx,[HF_PORT]
  6743                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6744 00002B2C B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6745 00002B31 EC                  <1> CMD_I2: IN	AL,DX
  6746                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6747 00002B32 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6748 00002B34 47                  <1> 	INC	eDI
  6749 00002B35 E2FA                <1> 	LOOP	CMD_I2
  6750 00002B37 E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6751 00002B3C 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6752 00002B3E FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6753 00002B41 75BC                <1> 	JNZ	SHORT CMD_I1
  6754                              <1> CMD_ABORT:
  6755 00002B43 C3                  <1> TM_OUT: RETn
  6756                              <1> 
  6757                              <1> ;----------------------------------------
  6758                              <1> ; COMMANDO				:
  6759                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6760                              <1> ;	NSECTOR RETURNS ZERO		:
  6761                              <1> ;----------------------------------------
  6762                              <1> COMMANDO:
  6763 00002B44 E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6764 00002B49 72F8                <1> 	JC	short CMD_ABORT
  6765 00002B4B 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6766 00002B4D E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6767 00002B52 75EF                <1> 	JNZ	short CMD_ABORT
  6768 00002B54 E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6769 00002B59 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6770                              <1> CMD_O1: ;PUSH	DS
  6771                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6772                              <1> 	;POP	DS
  6773                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6774                              <1> 	;MOV	DX,HF_PORT
  6775                              <1> 	; 01/02/2015
  6776 00002B5B 668B15[84670000]    <1> 	mov	dx, [HF_PORT]
  6777                              <1> 	;push	es
  6778                              <1> 	;pop	ds
  6779                              <1> 	;mov	cx, 256
  6780 00002B62 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6781 00002B67 FA                  <1> 	CLI
  6782 00002B68 FC                  <1> 	CLD
  6783 00002B69 F3666F              <1> 	REP	OUTSW
  6784 00002B6C FB                  <1> 	STI
  6785                              <1> 	;POP	DS			; RESTORE DS
  6786 00002B6D F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6787 00002B71 7419                <1> 	JZ	short CMD_O3
  6788 00002B73 E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6789 00002B78 72C9                <1> 	JC	short TM_OUT
  6790                              <1> 	;MOV	DX,HF_PORT
  6791 00002B7A 668B15[84670000]    <1> 	mov	dx, [HF_PORT]
  6792                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6793 00002B81 B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6794                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6795 00002B86 8A06                <1> 	mov	al, [esi]
  6796 00002B88 EE                  <1> 	OUT	DX,AL
  6797 00002B89 46                  <1> 	INC	eSI
  6798 00002B8A E2FA                <1> 	LOOP	CMD_O2
  6799                              <1> CMD_O3:
  6800 00002B8C E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6801 00002B91 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6802 00002B93 E830010000          <1> 	CALL	CHECK_STATUS
  6803 00002B98 75A9                <1> 	JNZ	short CMD_ABORT
  6804 00002B9A F605[256D0000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6805 00002BA1 75B8                <1> 	JNZ	SHORT CMD_O1
  6806                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6807 00002BA3 668B15[84670000]    <1> 	mov	dx, [HF_PORT]
  6808                              <1> 	;add	dl, 2
  6809 00002BAA FEC2                <1> 	inc	dl
  6810 00002BAC FEC2                <1> 	inc	dl
  6811 00002BAE EC                  <1> 	IN	AL,DX			;
  6812 00002BAF A8FF                <1> 	TEST	AL,0FFH 		;
  6813 00002BB1 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6814 00002BB3 C605[2F6D0000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6815                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6816                              <1> CMD_O4:
  6817 00002BBA C3                  <1> 	RETn
  6818                              <1> 
  6819                              <1> ;--------------------------------------------------------
  6820                              <1> ; COMMAND						:
  6821                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6822                              <1> ; OUTPUT						:
  6823                              <1> ;	BL = STATUS					:
  6824                              <1> ;	BH = ERROR REGISTER				:
  6825                              <1> ;--------------------------------------------------------
  6826                              <1> 
  6827                              <1> COMMAND:
  6828 00002BBB 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6829                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6830                              <1> COMMAND1:
  6831                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6832 00002BBC E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6833                              <1> 	;;POP	CX
  6834 00002BC1 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6835 00002BC3 803D[2F6D0000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6836                              <1> 	;JZ	short CMD_TIMEOUT
  6837                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6838                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6839 00002BCA 7507                <1> 	jne	short COMMAND4
  6840                              <1> CMD_TIMEOUT:
  6841 00002BCC C605[2F6D0000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6842                              <1> COMMAND4:
  6843 00002BD3 5B                  <1> 	POP	eBX
  6844 00002BD4 803D[2F6D0000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6845 00002BDB C3                  <1> 	RETn
  6846                              <1> COMMAND2:
  6847 00002BDC 5B                  <1> 	POP	eBX
  6848 00002BDD 57                  <1> 	PUSH	eDI
  6849 00002BDE C605[276D0000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6850 00002BE5 FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6851 00002BE6 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6852                              <1> 	;AND	AL,0BFH
  6853 00002BE8 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6854                              <1> 	;JMP	$+2
  6855                              <1> 	IODELAY
  2103 00002BEA EB00                <2>  jmp short $+2
  2104 00002BEC EB00                <2>  jmp short $+2
  6856 00002BEE E6A1                <1> 	OUT	INTB01,AL
  6857 00002BF0 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6858 00002BF2 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6859                              <1> 	;JMP	$+2
  6860                              <1> 	IODELAY
  2103 00002BF4 EB00                <2>  jmp short $+2
  2104 00002BF6 EB00                <2>  jmp short $+2
  6861 00002BF8 E621                <1> 	OUT	INTA01,AL
  6862 00002BFA FB                  <1> 	STI
  6863 00002BFB 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6864                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6865 00002BFD 668B15[84670000]    <1> 	mov	dx, [HF_PORT]
  6866 00002C04 FEC2                <1> 	inc	dl
  6867 00002C06 F605[316D0000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6868 00002C0D 7411                <1> 	JZ	short COMMAND3
  6869 00002C0F 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6870 00002C12 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6871 00002C14 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6872 00002C16 7208                <1> 	JB	short COMMAND3
  6873 00002C18 3C40                <1> 	CMP	AL,40H
  6874 00002C1A 7704                <1> 	JA	short COMMAND3
  6875 00002C1C 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6876                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6877                              <1> COMMAND3:
  6878 00002C20 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6879 00002C24 EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6880                              <1> 	IODELAY
  2103 00002C25 EB00                <2>  jmp short $+2
  2104 00002C27 EB00                <2>  jmp short $+2
  6881 00002C29 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6882 00002C2A 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6883 00002C2C 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6884 00002C30 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6885 00002C32 5F                  <1> 	POP	eDI
  6886 00002C33 C3                  <1> 	RETn				; ZERO FLAG IS SET
  6887                              <1> 
  6888                              <1> ;CMD_TIMEOUT:
  6889                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6890                              <1> ;COMMAND4:
  6891                              <1> ;	POP	BX
  6892                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6893                              <1> ;	RETn
  6894                              <1> 
  6895                              <1> ;----------------------------------------
  6896                              <1> ;	WAIT FOR INTERRUPT		:
  6897                              <1> ;----------------------------------------
  6898                              <1> ;WAIT:
  6899                              <1> _WAIT:
  6900 00002C34 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6901                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6902                              <1> 	;CLC
  6903                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6904                              <1> 	;INT	15H
  6905                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6906                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6907                              <1> 
  6908                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6909                              <1> 	;; 21/02/2015
  6910                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6911                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6912 00002C35 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6913                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6914                              <1> ;-----	WAIT LOOP
  6915                              <1> 
  6916                              <1> WT1:	
  6917                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6918 00002C3A F605[276D0000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6919                              <1> 	;LOOPZ	WT1
  6920 00002C41 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6921                              <1> 	;DEC	BL
  6922                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6923                              <1> 
  6924                              <1> WT1_hi:
  6925 00002C43 E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6926 00002C45 A810                <1> 	test	al, 10h			; transition on memory
  6927 00002C47 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6928                              <1> WT1_lo:
  6929 00002C49 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6930 00002C4B A810                <1> 	test	al, 10h			
  6931 00002C4D 74FA                <1> 	jz	short WT1_lo
  6932 00002C4F E2E9                <1> 	loop	WT1
  6933                              <1> 	;;or	bl, bl
  6934                              <1> 	;;jz	short WT2	
  6935                              <1> 	;;dec	bl
  6936                              <1> 	;;jmp	short WT1
  6937                              <1> 	;dec	bl
  6938                              <1> 	;jnz	short WT1	
  6939                              <1> 
  6940 00002C51 C605[2F6D0000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6941 00002C58 EB0E                <1> 	JMP	SHORT WT4
  6942 00002C5A C605[2F6D0000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6943 00002C61 C605[276D0000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6944 00002C68 803D[2F6D0000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6945 00002C6F C3                  <1> 	RETn
  6946                              <1> 
  6947                              <1> ;----------------------------------------
  6948                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  6949                              <1> ;----------------------------------------
  6950                              <1> NOT_BUSY:
  6951 00002C70 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6952                              <1> 	;PUSH	eBX
  6953                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6954 00002C71 668B15[84670000]    <1> 	mov	DX, [HF_PORT]
  6955 00002C78 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  6956                              <1> 	;MOV	BL,DELAY_1
  6957                              <1> 					; wait for 10 seconds
  6958                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  6959                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  6960                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  6961 00002C7B B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  6962                              <1> 	;
  6963                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  6964                              <1> NB1:	
  6965 00002C80 EC                  <1> 	IN	AL,DX			; CHECK STATUS
  6966                              <1> 	;TEST	AL,ST_BUSY
  6967 00002C81 2480                <1> 	and	al, ST_BUSY
  6968                              <1> 	;LOOPNZ	NB1
  6969 00002C83 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  6970                              <1> 	;DEC	BL			
  6971                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  6972                              <1> 
  6973 00002C85 E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  6974 00002C87 A810                <1> 	TEST	AL,010H			; transition on memory
  6975 00002C89 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  6976 00002C8B E461                <1> NB1_lo: IN	AL,SYS1
  6977 00002C8D A810                <1> 	TEST	AL,010H
  6978 00002C8F 74FA                <1> 	JZ	short NB1_lo
  6979 00002C91 E2ED                <1> 	LOOP	NB1
  6980                              <1> 	;dec	bl
  6981                              <1> 	;jnz	short NB1
  6982                              <1> 	;
  6983                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  6984                              <1> ;;	jb	short NB1
  6985                              <1> 	;
  6986                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  6987                              <1> 	;JMP	SHORT NB3
  6988 00002C93 B080                <1> 	mov	al, TIME_OUT
  6989                              <1> NB2:	
  6990                              <1> 	;MOV	byte [DISK_STATUS1],0
  6991                              <1> ;NB3:	
  6992                              <1> 	;POP	eBX
  6993 00002C95 A2[2F6D0000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  6994                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6995 00002C9A 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  6996 00002C9C C3                  <1> 	RETn
  6997                              <1> 
  6998                              <1> ;----------------------------------------
  6999                              <1> ;	WAIT FOR DATA REQUEST		:
  7000                              <1> ;----------------------------------------
  7001                              <1> WAIT_DRQ:
  7002                              <1> 	;MOV	CX,DELAY_3
  7003                              <1> 	;MOV	DX,HF_PORT+7
  7004 00002C9D 668B15[84670000]    <1> 	mov	dx, [HF_PORT]
  7005 00002CA4 80C207              <1> 	add	dl, 7
  7006                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  7007                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  7008                              <1> 					; (but it is written as 2000
  7009                              <1> 					; micro seconds in ATORGS.ASM file
  7010                              <1> 					; of Award Bios - 1999, D1A0622)
  7011 00002CA7 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  7012 00002CAC EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  7013 00002CAD A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  7014 00002CAF 7516                <1> 	JNZ	short WQ_OK
  7015                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  7016                              <1> WQ_hi:	
  7017 00002CB1 E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  7018 00002CB3 A810                <1> 	TEST	AL,010H			; transition on memory
  7019 00002CB5 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  7020 00002CB7 E461                <1> WQ_lo:  IN      AL,SYS1
  7021 00002CB9 A810                <1> 	TEST	AL,010H
  7022 00002CBB 74FA                <1> 	JZ	SHORT WQ_lo
  7023 00002CBD E2ED                <1> 	LOOP	WQ_1
  7024                              <1> 
  7025 00002CBF C605[2F6D0000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  7026 00002CC6 F9                  <1> 	STC
  7027                              <1> WQ_OK:
  7028 00002CC7 C3                  <1> 	RETn
  7029                              <1> ;WQ_OK:	;CLC
  7030                              <1> ;	RETn
  7031                              <1> 
  7032                              <1> ;----------------------------------------
  7033                              <1> ;	CHECK FIXED DISK STATUS 	:
  7034                              <1> ;----------------------------------------
  7035                              <1> CHECK_STATUS:
  7036 00002CC8 E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  7037 00002CCD 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  7038 00002CCF A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  7039 00002CD1 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  7040 00002CD3 E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  7041                              <1> CHECK_S1:
  7042 00002CD8 803D[2F6D0000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  7043 00002CDF C3                  <1> 	RETn
  7044                              <1> 
  7045                              <1> ;----------------------------------------
  7046                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  7047                              <1> ;----------------------------------------
  7048                              <1> CHECK_ST:
  7049                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  7050 00002CE0 668B15[84670000]    <1> 	mov	dx, [HF_PORT]
  7051 00002CE7 80C207              <1> 	add	dl, 7
  7052 00002CEA EC                  <1> 	IN	AL,DX
  7053 00002CEB A2[256D0000]        <1> 	MOV	[HF_STATUS],AL
  7054 00002CF0 B400                <1> 	MOV	AH,0
  7055 00002CF2 A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  7056 00002CF4 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  7057 00002CF6 B4CC                <1> 	MOV	AH,WRITE_FAULT
  7058 00002CF8 A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7059 00002CFA 7514                <1> 	JNZ	short CKST_EXIT
  7060 00002CFC B4AA                <1> 	MOV	AH,NOT_RDY
  7061 00002CFE A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7062 00002D00 740E                <1> 	JZ	short CKST_EXIT
  7063 00002D02 B440                <1> 	MOV	AH,BAD_SEEK
  7064 00002D04 A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7065 00002D06 7408                <1> 	JZ	short CKST_EXIT
  7066 00002D08 B411                <1> 	MOV	AH,DATA_CORRECTED
  7067 00002D0A A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7068 00002D0C 7502                <1> 	JNZ	short CKST_EXIT
  7069 00002D0E B400                <1> 	MOV	AH,0
  7070                              <1> CKST_EXIT:
  7071 00002D10 8825[2F6D0000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7072 00002D16 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7073 00002D19 7403                <1> 	JZ	short CKST_EX1
  7074 00002D1B 80FC00              <1> 	CMP	AH,0
  7075                              <1> CKST_EX1:
  7076 00002D1E C3                  <1> 	RETn
  7077                              <1> 
  7078                              <1> ;----------------------------------------
  7079                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7080                              <1> ;----------------------------------------
  7081                              <1> CHECK_ER:
  7082                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7083 00002D1F 668B15[84670000]    <1> 	mov	dx, [HF_PORT]		;
  7084 00002D26 FEC2                <1> 	inc	dl
  7085 00002D28 EC                  <1> 	IN	AL,DX
  7086 00002D29 A2[266D0000]        <1> 	MOV	[HF_ERROR],AL
  7087 00002D2E 53                  <1> 	PUSH	eBX ; 21/02/2015
  7088 00002D2F B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7089 00002D34 D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7090 00002D36 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7091 00002D38 E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7092 00002D3A BB[78670000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7093 00002D3F 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7094                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7095                              <1> 	;mov	ah, [bx]
  7096 00002D41 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7097 00002D43 8825[2F6D0000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7098 00002D49 5B                  <1> 	POP	eBX
  7099 00002D4A 80FC00              <1> 	CMP	AH,0
  7100 00002D4D C3                  <1> 	RETn
  7101                              <1> 
  7102                              <1> ;--------------------------------------------------------
  7103                              <1> ; CHECK_DMA						:
  7104                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7105                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7106                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7107                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7108                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7109                              <1> ;  -ERROR OTHERWISE					:
  7110                              <1> ;--------------------------------------------------------
  7111                              <1> CHECK_DMA:
  7112                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7113                              <1> 	; 24/12/2021
  7114 00002D4E 50                  <1> 	push	eax
  7115 00002D4F 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7116 00002D53 F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7117 00002D57 7404                <1> 	JZ	short CKD1
  7118 00002D59 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7119 00002D5D 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7120 00002D60 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7121 00002D62 7207                <1> 	JB	short CKDERR		; TOO MANY
  7122 00002D64 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7123 00002D66 7203                <1> 	JB	short CKDERR		; ERROR
  7124 00002D68 F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7125                              <1> 	;POP	AX
  7126                              <1> 	; 24/12/2021
  7127 00002D69 58                  <1> 	pop	eax
  7128 00002D6A C3                  <1> 	RETn				; NORMAL RETURN
  7129 00002D6B F9                  <1> CKDERR: STC				; INDICATE ERROR
  7130 00002D6C C605[2F6D0000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7131                              <1> 	;POP	AX
  7132                              <1> 	; 24/12/2021
  7133 00002D73 58                  <1> 	pop	eax	
  7134 00002D74 C3                  <1> 	RETn
  7135                              <1> 
  7136                              <1> ;----------------------------------------
  7137                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7138                              <1> ;----------------------------------------
  7139                              <1> 					
  7140                              <1> ; INPUT -> DL = 0 based drive number
  7141                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7142                              <1> 
  7143                              <1> GET_VEC:
  7144                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7145                              <1> 	;MOV	ES,AX
  7146                              <1> 	;TEST	DL,1
  7147                              <1> 	;JZ	short GV_0
  7148                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7149                              <1> ;	JMP	SHORT GV_EXIT
  7150                              <1> ;GV_0:
  7151                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7152                              <1> ;
  7153                              <1> 	;xor	bh, bh
  7154 00002D75 31DB                <1> 	xor	ebx, ebx
  7155 00002D77 88D3                <1> 	mov	bl, dl
  7156                              <1> 	;;02/01/2015
  7157                              <1> 	;;shl	bl, 1			; port address offset
  7158                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7159                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7160 00002D79 C0E302              <1> 	shl	bl, 2	;;
  7161                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7162 00002D7C 81C3[346D0000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7163                              <1> 	;push	word [bx+2]		; dpt segment
  7164                              <1> 	;pop	es
  7165                              <1> 	;mov	bx, [bx]		; dpt offset
  7166 00002D82 8B1B                <1> 	mov	ebx, [ebx]		
  7167                              <1> ;GV_EXIT:
  7168 00002D84 C3                  <1> 	RETn
  7169                              <1> 
  7170                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7171                              <1> hdc1_int: ; 21/02/2015
  7172                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7173                              <1> ;								:
  7174                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7175                              <1> ;								:
  7176                              <1> ;----------------------------------------------------------------
  7177                              <1> 
  7178                              <1> ; 22/12/2014
  7179                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7180                              <1> ;	 '11/15/85'
  7181                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7182                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7183                              <1> 
  7184                              <1> ;int_76h:
  7185                              <1> HD_INT:
  7186                              <1> 	;push	ax
  7187                              <1> 	; 24/12/2021
  7188 00002D85 50                  <1> 	push	eax
  7189 00002D86 1E                  <1> 	push	ds
  7190                              <1> 	;CALL	DDS
  7191                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7192 00002D87 66B81000            <1> 	mov	ax, KDATA
  7193 00002D8B 8ED8                <1> 	mov 	ds, ax
  7194                              <1> 	;
  7195                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7196                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7197 00002D8D C605[276D0000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7198                              <1> 	;
  7199                              <1> 	;push	dx
  7200                              <1> 	; 24/12/2021
  7201 00002D94 52                  <1> 	push	edx
  7202 00002D95 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7203                              <1> 					; Clear Controller
  7204                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7205 00002D99 EC                  <1> 	in	al, dx			;
  7206                              <1> 	;pop	dx
  7207                              <1> 	; 24/12/2021
  7208 00002D9A 5A                  <1> 	pop	edx
  7209                              <1> 	NEWIODELAY
  2108 00002D9B E6EB                <2>  out 0EBh,al
  7210                              <1> 	;
  7211 00002D9D B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7212 00002D9F E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7213                              <1> 	;JMP	$+2			; WAIT
  7214                              <1> 	NEWIODELAY
  2108 00002DA1 E6EB                <2>  out 0EBh,al
  7215 00002DA3 E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7216 00002DA5 1F                  <1> 	pop	ds
  7217                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7218                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7219                              <1> 	;INT	15H			;  INTERRUPT
  7220                              <1> irq15_iret: ; 25/02/2015
  7221                              <1> 	;pop	ax
  7222                              <1> 	; 24/12/2021
  7223 00002DA6 58                  <1> 	pop	eax
  7224 00002DA7 CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7225                              <1> 
  7226                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7227                              <1> hdc2_int: ; 21/02/2015
  7228                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7229                              <1> ;								:
  7230                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7231                              <1> ;								:
  7232                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7233                              <1> 
  7234                              <1> ;int_77h:
  7235                              <1> HD1_INT:
  7236                              <1> 	;push	ax
  7237                              <1> 	; 24/12/2021
  7238 00002DA8 50                  <1> 	push	eax
  7239                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7240                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7241 00002DA9 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7242 00002DAB E6A0                <1> 	out	0A0h, al
  7243 00002DAD EB00                <1>         jmp short $+2
  7244 00002DAF EB00                <1> 	jmp short $+2
  7245 00002DB1 E4A0                <1> 	in	al, 0A0h
  7246 00002DB3 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7247 00002DB5 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7248                              <1> 	;
  7249 00002DB7 1E                  <1> 	push	ds
  7250                              <1> 	;CALL	DDS
  7251                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7252 00002DB8 66B81000            <1> 	mov	ax, KDATA
  7253 00002DBC 8ED8                <1> 	mov 	ds, ax
  7254                              <1> 	;
  7255                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7256                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7257 00002DBE 800D[276D0000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7258                              <1> 	;
  7259                              <1> 	;push	dx
  7260                              <1> 	; 24/12/2021
  7261 00002DC5 52                  <1> 	push	edx
  7262 00002DC6 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7263                              <1> 					; Clear Controller (Award BIOS 1999)
  7264 00002DCA EBCD                <1> 	jmp	short Clear_IRQ1415
  7265                              <1> 
  7266                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7267                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7268                              <1> 
  7269                              <1> ;////////////////////////////////////////////////////////////////////
  7270                              <1> ;; END OF DISK I/O SYTEM ///
  2045                                  %include 'memory.inc'  ; 09/03/2015
  2046                              <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2047                              <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.18) - MEMORY.INC
  2048                              <1> ; Last Modification: 03/02/2022 [ 31/12/2021 (Retro UNIX 386 v1.1) ]
  2049                              <1> ;
  2050                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2051                              <1> 
  2052                              <1> ; Ref: Retro UNIX 386 v1.1, Kernel v0.2.1.1 - MEMORY.INC (31/12/2021)
  2053                              <1> 
  2054                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2055                              <1> 
  2056                              <1> ;;04/11/2014 (unix386.s)	
  2057                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2058                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2059                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2060                              <1> ;;
  2061                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2062                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2063                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2064                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2065                              <1> 
  2066                              <1> ; 27/04/2015
  2067                              <1> ; 09/03/2015
  2068                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2069                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2070                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2071                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2072                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2073                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2074                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2075                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2076                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2077                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2078                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2079                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2080                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2081                              <1> SWP_DISK_READ_ERR 	   equ 40
  2082                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2083                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2084                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2085                              <1> SWP_DISK_WRITE_ERR         equ 44
  2086                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2087                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2088                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2089                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2090                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2091                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2092                              <1> 					; (Indicates that the page is not allocated
  2093                              <1> 					; for the process, it is a shared or system
  2094                              <1>                                         ; page, it must not be deallocated!)
  2095                              <1> ; 14/12/2020
  2096                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2097                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2098                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2099                              <1> 				; (Out of memory allocation table)	
  2100                              <1> ;
  2101                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2102                              <1> ;;
  2103                              <1> ;; 10/10/2014
  2104                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2105                              <1> ;;
  2106                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2107                              <1> ;;	(virtual address = physical address)
  2108                              <1> ;; KERNEL PAGE TABLES:
  2109                              <1> ;;	Kernel page directory and all page tables are
  2110                              <1> ;;	on memory as initialized, as equal to physical memory
  2111                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2112                              <1> ;;
  2113                              <1> ;;	what for: User pages may be swapped out, when accessing
  2114                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2115                              <1> ;;	kernel would have to swap it in! But it is also may be
  2116                              <1> ;;	in use by a user process. (In system/kernel mode
  2117                              <1> ;;	kernel can access all memory pages even if they are
  2118                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2119                              <1> ;;	cause conflicts.) 
  2120                              <1> ;;	
  2121                              <1> ;;	As result of these conditions,
  2122                              <1> ;;	all kernel pages must be initialized as equal to 
  2123                              <1> ;;	physical layout for preventing page faults. 
  2124                              <1> ;;	Also, calling "allocate page" procedure after
  2125                              <1> ;;	a page fault can cause another page fault (double fault)
  2126                              <1> ;;	if all kernel page tables would not be initialized.
  2127                              <1> ;;
  2128                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2129                              <1> ;;	memory allocation table. (double word aligned)
  2130                              <1> ;;
  2131                              <1> ;;	[next_page] = first/next free space to be searched
  2132                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2133                              <1> ;;
  2134                              <1> ;;	[last_page] = End of memory (users space), as offset
  2135                              <1> ;;	to memory allocation table. (double word aligned)
  2136                              <1> ;;
  2137                              <1> ;; USER PAGE TABLES:
  2138                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2139                              <1> ;;		'ready only' marked copies of the 
  2140                              <1> ;;		parent process's page table entries (for
  2141                              <1> ;;		same physical memory).
  2142                              <1> ;;		(A page will be copied to a new page after
  2143                              <1> ;;		 if it causes R/W page fault.)
  2144                              <1> ;;
  2145                              <1> ;;	Every user process has own (different)
  2146                              <1> ;;	page directory and page tables.	
  2147                              <1> ;;
  2148                              <1> ;;	Code starts at virtual address 0, always.
  2149                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2150                              <1> ;;	(Programs can be written/developed as simple
  2151                              <1> ;;	 flat memory programs.)
  2152                              <1> ;;
  2153                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2154                              <1> ;;	Memory page will be allocated by kernel only 
  2155                              <1> ;;		(in kernel/system mode only).
  2156                              <1> ;;	* After a
  2157                              <1> ;;	  - 'not present' page fault
  2158                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2159                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2160                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2161                              <1> ;;	  request by running process.
  2162                              <1> ;;	* While creating a process, allocating a new buffer,
  2163                              <1> ;;	  new page tables etc.
  2164                              <1> ;;
  2165                              <1> ;;	At first,
  2166                              <1> ;;	- 'allocate page' procedure will be called;
  2167                              <1> ;,	   if it will return with a valid (>0) physical address
  2168                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2169                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2170                              <1> ;;	- 'allocate page' will be called for allocating page
  2171                              <1> ;;	   directory, page table and running space (data/code).
  2172                              <1> ;;	- every successful 'allocate page' call will decrease
  2173                              <1> ;;	  'free_pages' count (pointer).
  2174                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2175                              <1> ;;	  if 'free_pages' points to a ZERO.
  2176                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2177                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2178                              <1> ;;	  error except errors caused by attribute conflicts.
  2179                              <1> ;;	 (swapper functions)	 
  2180                              <1> ;;					
  2181                              <1> ;;	At second,
  2182                              <1> ;;	- page directory entry will be updated then page table
  2183                              <1> ;;	  entry will be updated.		
  2184                              <1> ;;
  2185                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2186                              <1> ;;	- M.A.T. has a size according to available memory as
  2187                              <1> ;;	  follows:
  2188                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2189                              <1> ;;		  - a bit with value of 0 means allocated page
  2190                              <1> ;;		  - a bit with value of 1 means a free page
  2191                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2192                              <1> ;;	  depending on M.A.T.
  2193                              <1> ;;		(NOTE: Free page count will not be checked
  2194                              <1> ;;		again -on M.A.T.- after initialization. 
  2195                              <1> ;;		Kernel will trust on initial count.)
  2196                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2197                              <1> ;;	  and it will be increased by deallocation procedures.
  2198                              <1> ;;	
  2199                              <1> ;;	- Available memory will be calculated during
  2200                              <1> ;;	  the kernel's initialization stage (in real mode).
  2201                              <1> ;;	  Memory allocation table and kernel page tables 
  2202                              <1> ;;	  will be formatted/sized as result of available
  2203                              <1> ;;	  memory calculation before paging is enabled.
  2204                              <1> ;;
  2205                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2206                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2207                              <1> ;;	- Memory allocation for kernel page directory size 
  2208                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2209                              <1> ;;	  for page tables)
  2210                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2211                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2212                              <1> ;;	- User (available) space will be started 
  2213                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2214                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2215                              <1> ;;	  memory allocation table and kernel's page directory
  2216                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2217                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2218                              <1> ;; 	  for buffers.
  2219                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2220                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2221                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2222                              <1> ;;
  2223                              <1> ;; For 1GB Available Memory:
  2224                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2225                              <1> ;;	- Memory allocation for kernel page directory size 
  2226                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2227                              <1> ;;	  for page tables)
  2228                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2229                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2230                              <1> ;;	- User (available) space will be started 
  2231                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2232                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2233                              <1> ;;	  memory allocation table and kernel's page directory
  2234                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2235                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2236                              <1> ;; 	  for buffers.
  2237                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2238                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2239                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2240                              <1> ;;
  2241                              <1> ;;
  2242                              <1> 
  2243                              <1> ;;************************************************************************************
  2244                              <1> ;; 
  2245                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2246                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2247                              <1> 
  2248                              <1> ;; Main factor: "sys fork" system call 
  2249                              <1> ;;	
  2250                              <1> ;; 		FORK
  2251                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2252                              <1> ;;  writable pages ---->|
  2253                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2254                              <1> ;; 
  2255                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2256                              <1> ;; 
  2257                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2258                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2259                              <1> ;;       -while R/W bit is 0-. 
  2260                              <1> ;; 
  2261                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2262                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2263                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2264                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2265                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2266                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2267                              <1> ;; 
  2268                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2269                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2270                              <1> ;;   Parent's PTE attributes are not changed.
  2271                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2272                              <1> ;;    destroy/mix previous fork result).
  2273                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2274                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2275                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2276                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2277                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2278                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2279                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2280                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2281                              <1> ;; 
  2282                              <1> ;; !? WHAT FOR (duplication after duplication):
  2283                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2284                              <1> ;; program/executable code continues from specified location as child process, 
  2285                              <1> ;; returns back previous code location as parent process, every child after 
  2286                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2287                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2288                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2289                              <1> ;; was copied to child's process segment (all of code and data) according to
  2290                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2291                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2292                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2293                              <1> ;; (complete running image of parent process) to the child process; 
  2294                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2295                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2296                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2297                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2298                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2299                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2300                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2301                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2302                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2303                              <1> ;; for sharing same read only pages between parent and child processes.
  2304                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2305                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2306                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2307                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2308                              <1> ;; -deallocation problem-.
  2309                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2310                              <1> ;; 
  2311                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2312                              <1> ;; # Page fault handler will do those:
  2313                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2314                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2315                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2316                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2317                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2318                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2319                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2320                              <1> ;;     to child process.)	
  2321                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2322                              <1> ;; # Page fault handler will do those:
  2323                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2324                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2325                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2326                              <1> ;;     address or not. 
  2327                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2328                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2329                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2330                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2331                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2332                              <1> ;; 
  2333                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2334                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2335                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2336                              <1> ;;       duplication method details, it is not possible multiple child processes
  2337                              <1> ;;       were using same page with duplicated PTEs.
  2338                              <1> ;; 
  2339                              <1> ;;************************************************************************************   
  2340                              <1> 
  2341                              <1> ;; 08/10/2014
  2342                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2343                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2344                              <1> 
  2345                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2346                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2347                              <1> ;; (25/08/2014, Revision: 5057) file 
  2348                              <1> ;; by KolibriOS Team (2004-2012)
  2349                              <1> 
  2350                              <1> allocate_page:
  2351                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2352                              <1> 	; 01/07/2015
  2353                              <1> 	; 05/05/2015
  2354                              <1> 	; 30/04/2015
  2355                              <1> 	; 16/10/2014
  2356                              <1> 	; 08/10/2014
  2357                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2358                              <1> 	;
  2359                              <1> 	; INPUT -> none
  2360                              <1> 	;
  2361                              <1> 	; OUTPUT ->
  2362                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2363                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2364                              <1> 	;
  2365                              <1> 	;	CF = 1 and EAX = 0 
  2366                              <1> 	; 		   if there is not a free page to be allocated	
  2367                              <1> 	;
  2368                              <1> 	; Modified Registers -> none (except EAX)
  2369                              <1> 	;
  2370 00002DCC A1[A06C0000]        <1> 	mov	eax, [free_pages]
  2371 00002DD1 21C0                <1> 	and	eax, eax
  2372 00002DD3 7438                <1> 	jz	short out_of_memory
  2373                              <1> 	;
  2374 00002DD5 53                  <1> 	push	ebx
  2375 00002DD6 51                  <1> 	push	ecx
  2376                              <1> 	;
  2377 00002DD7 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2378 00002DDC 89D9                <1> 	mov	ecx, ebx
  2379                              <1>  				     ; NOTE: 32 (first_page) is initial
  2380                              <1> 				     ; value of [next_page].
  2381                              <1> 				     ; It points to the first available
  2382                              <1> 				     ; page block for users (ring 3) ...	
  2383                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2384                              <1> 				     ; (at the of the first 4 MB)		
  2385 00002DDE 031D[A46C0000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2386                              <1> 				 ; next_free_page >> 5
  2387 00002DE4 030D[A86C0000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2388                              <1> 				 ; (total_pages - 1) >> 5
  2389                              <1> al_p_scan:
  2390 00002DEA 39CB                <1> 	cmp	ebx, ecx
  2391 00002DEC 770A                <1> 	ja	short al_p_notfound
  2392                              <1> 	;
  2393                              <1> 	; 01/07/2015
  2394                              <1> 	; AMD64 Architecture Programmers Manual
  2395                              <1> 	; Volume 3:
  2396                              <1> 	; General-Purpose and System Instructions
  2397                              <1> 	;
  2398                              <1> 	; BSF - Bit Scan Forward
  2399                              <1> 	;
  2400                              <1> 	;   Searches the value in a register or a memory location
  2401                              <1> 	;   (second operand) for the least-significant set bit. 
  2402                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2403                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2404                              <1> 	;   register (first operand). If the second operand contains 0, 
  2405                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2406                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2407                              <1> 	;   of the searched value
  2408                              <1> 	;
  2409 00002DEE 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2410                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2411                              <1> 			   ; loads the destination with an index to
  2412                              <1> 			   ; first set bit. (0 -> 31) 
  2413                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2414 00002DF1 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2415                              <1> 			 ;
  2416                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2417                              <1> 			 ;	  with value of 1 means 
  2418                              <1> 			 ;	  the corresponding page is free 
  2419                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2420 00002DF3 83C304              <1> 	add	ebx, 4
  2421                              <1> 			 ; We return back for searching next page block
  2422                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2423                              <1> 			 ;	 we always will find at least 1 free page here.
  2424 00002DF6 EBF2                <1>         jmp     short al_p_scan
  2425                              <1> 	;
  2426                              <1> al_p_notfound:
  2427 00002DF8 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2428 00002DFE 890D[A46C0000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2429                              <1> 				 ; (deallocate_page procedure will change it)
  2430 00002E04 31C0                <1> 	xor	eax, eax
  2431 00002E06 A3[A06C0000]        <1> 	mov	[free_pages], eax ; 0
  2432 00002E0B 59                  <1> 	pop	ecx
  2433 00002E0C 5B                  <1> 	pop	ebx
  2434                              <1> 	;
  2435                              <1> ; 24/12/2021
  2436                              <1> ; ('swap_out' procedure call is disabled)
  2437                              <1> 
  2438                              <1> out_of_memory:
  2439                              <1> ;	call	swap_out
  2440                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2441                              <1> ;	;
  2442                              <1> ;	sub 	eax, eax ; 0
  2443 00002E0D F9                  <1> 	stc
  2444 00002E0E C3                  <1> 	retn
  2445                              <1> 
  2446                              <1> al_p_found:
  2447 00002E0F 89D9                <1> 	mov	ecx, ebx
  2448 00002E11 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2449 00002E17 890D[A46C0000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2450                              <1> 				 ; address/offset (to the next)
  2451 00002E1D FF0D[A06C0000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2452                              <1> 	;
  2453 00002E23 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2454                              <1> 				 ; is copied into the Carry Flag and then cleared
  2455                              <1> 				 ; in the destination.
  2456                              <1> 				 ;
  2457                              <1> 				 ; Reset the bit which is corresponding to the 
  2458                              <1> 				 ; (just) allocated page.
  2459                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2460 00002E26 C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2461 00002E29 01C8                <1> 	add	eax, ecx	 ; = page number
  2462 00002E2B C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2463                              <1> 	; EAX = physical address of memory page
  2464                              <1> 	;
  2465                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2466                              <1> 	;       according to this EAX value...
  2467 00002E2E 59                  <1> 	pop	ecx
  2468 00002E2F 5B                  <1> 	pop	ebx
  2469                              <1> al_p_ok:
  2470 00002E30 C3                  <1> 	retn
  2471                              <1> 
  2472                              <1> make_page_dir:
  2473                              <1> 	; 18/04/2015
  2474                              <1> 	; 12/04/2015
  2475                              <1> 	; 23/10/2014
  2476                              <1> 	; 16/10/2014
  2477                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2478                              <1> 	;
  2479                              <1> 	; INPUT ->
  2480                              <1> 	;	none
  2481                              <1> 	; OUTPUT ->
  2482                              <1> 	;	(EAX = 0)
  2483                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2484                              <1> 	;	cf = 0 ->
  2485                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2486                              <1> 	;		  process/user.
  2487                              <1> 	;
  2488                              <1> 	; Modified Registers -> EAX
  2489                              <1> 	;
  2490 00002E31 E896FFFFFF          <1> 	call	allocate_page
  2491 00002E36 7216                <1> 	jc	short mkpd_error
  2492                              <1> 	;
  2493 00002E38 A3[AF700000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2494                              <1> 				  ; (Physical address)
  2495                              <1> clear_page:
  2496                              <1> 	; 18/04/2015
  2497                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2498                              <1> 	;
  2499                              <1> 	; INPUT ->
  2500                              <1> 	;	EAX = physical address of the page
  2501                              <1> 	; OUTPUT ->
  2502                              <1> 	;	all bytes of the page will be cleared
  2503                              <1> 	;
  2504                              <1> 	; Modified Registers -> none
  2505                              <1> 	;
  2506 00002E3D 57                  <1> 	push	edi
  2507 00002E3E 51                  <1> 	push	ecx
  2508 00002E3F 50                  <1> 	push	eax
  2509 00002E40 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2510 00002E45 89C7                <1> 	mov	edi, eax
  2511 00002E47 31C0                <1> 	xor	eax, eax
  2512 00002E49 F3AB                <1> 	rep	stosd
  2513 00002E4B 58                  <1> 	pop	eax
  2514 00002E4C 59                  <1> 	pop	ecx
  2515 00002E4D 5F                  <1> 	pop	edi
  2516                              <1> mkpd_error:
  2517                              <1> mkpt_error:
  2518 00002E4E C3                  <1> 	retn
  2519                              <1> 
  2520                              <1> make_page_table:
  2521                              <1> 	; 23/06/2015
  2522                              <1> 	; 18/04/2015
  2523                              <1> 	; 12/04/2015
  2524                              <1> 	; 16/10/2014
  2525                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2526                              <1> 	;
  2527                              <1> 	; INPUT ->
  2528                              <1> 	;	EBX = virtual (linear) address
  2529                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2530                              <1> 	;	      (higher 20 bits must be ZERO)
  2531                              <1> 	;	      (bit 0 must be 1)	 
  2532                              <1> 	;	u.pgdir = page directory (physical) address
  2533                              <1> 	; OUTPUT ->
  2534                              <1> 	;	EDX = Page directory entry address
  2535                              <1> 	;	EAX = Page table address
  2536                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2537                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2538                              <1> 	;
  2539                              <1> 	; Modified Registers -> EAX, EDX
  2540                              <1> 	;
  2541 00002E4F E878FFFFFF          <1> 	call	allocate_page
  2542 00002E54 72F8                <1> 	jc	short mkpt_error
  2543 00002E56 E811000000          <1> 	call	set_pde	
  2544 00002E5B EBE0                <1> 	jmp	short clear_page
  2545                              <1> 
  2546                              <1> make_page:
  2547                              <1> 	; 24/07/2015
  2548                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2549                              <1> 	;
  2550                              <1> 	; INPUT ->
  2551                              <1> 	;	EBX = virtual (linear) address
  2552                              <1> 	;	ECX = page attributes (lower 12 bits)
  2553                              <1> 	;	      (higher 20 bits must be ZERO)
  2554                              <1> 	;	      (bit 0 must be 1)	 
  2555                              <1> 	;	u.pgdir = page directory (physical) address
  2556                              <1> 	; OUTPUT ->
  2557                              <1> 	;	EBX = Virtual address
  2558                              <1> 	;	(EDX = PTE value)
  2559                              <1> 	;	EAX = Physical address
  2560                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2561                              <1> 	;
  2562                              <1> 	; Modified Registers -> EAX, EDX
  2563                              <1> 	;
  2564 00002E5D E86AFFFFFF          <1> 	call	allocate_page
  2565 00002E62 7207                <1> 	jc	short mkp_err
  2566 00002E64 E821000000          <1> 	call	set_pte	
  2567 00002E69 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2568                              <1> mkp_err:
  2569 00002E6B C3                  <1> 	retn
  2570                              <1> 
  2571                              <1> set_pde:	; Set page directory entry (PDE)
  2572                              <1> 	; 20/07/2015
  2573                              <1> 	; 18/04/2015
  2574                              <1> 	; 12/04/2015
  2575                              <1> 	; 23/10/2014
  2576                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2577                              <1> 	;
  2578                              <1> 	; INPUT ->
  2579                              <1> 	;	EAX = physical address
  2580                              <1> 	;	      (use present value if EAX = 0)
  2581                              <1> 	;	EBX = virtual (linear) address
  2582                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2583                              <1> 	;	      (higher 20 bits must be ZERO)
  2584                              <1> 	;	      (bit 0 must be 1)	 
  2585                              <1> 	;	u.pgdir = page directory (physical) address
  2586                              <1> 	; OUTPUT ->
  2587                              <1> 	;	EDX = PDE address
  2588                              <1> 	;	EAX = page table address (physical)
  2589                              <1> 	;	;(CF=1 -> Invalid page address)
  2590                              <1> 	;
  2591                              <1> 	; Modified Registers -> EDX
  2592                              <1> 	;
  2593 00002E6C 89DA                <1> 	mov	edx, ebx
  2594 00002E6E C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2595 00002E71 C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2596 00002E74 0315[AF700000]      <1> 	add	edx, [u.pgdir]
  2597                              <1> 	;
  2598 00002E7A 21C0                <1> 	and	eax, eax
  2599 00002E7C 7506                <1> 	jnz	short spde_1
  2600                              <1> 	;
  2601 00002E7E 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2602                              <1> 	;test	al, 1
  2603                              <1> 	;jz	short spde_2
  2604 00002E80 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2605                              <1> spde_1:
  2606                              <1> 	;and	cx, 0FFFh
  2607 00002E84 8902                <1> 	mov	[edx], eax
  2608 00002E86 66090A              <1> 	or	[edx], cx
  2609 00002E89 C3                  <1> 	retn
  2610                              <1> ;spde_2: ; error
  2611                              <1> ;	stc
  2612                              <1> ;	retn
  2613                              <1> 
  2614                              <1> set_pte:	; Set page table entry (PTE)
  2615                              <1> 	; 24/07/2015
  2616                              <1> 	; 20/07/2015
  2617                              <1> 	; 23/06/2015
  2618                              <1> 	; 18/04/2015
  2619                              <1> 	; 12/04/2015
  2620                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2621                              <1> 	;
  2622                              <1> 	; INPUT ->
  2623                              <1> 	;	EAX = physical page address
  2624                              <1> 	;	      (use present value if EAX = 0)
  2625                              <1> 	;	EBX = virtual (linear) address
  2626                              <1> 	;	ECX = page attributes (lower 12 bits)
  2627                              <1> 	;	      (higher 20 bits must be ZERO)
  2628                              <1> 	;	      (bit 0 must be 1)	 
  2629                              <1> 	;	u.pgdir = page directory (physical) address
  2630                              <1> 	; OUTPUT ->
  2631                              <1> 	;	EAX = physical page address
  2632                              <1> 	;	(EDX = PTE value)
  2633                              <1> 	;	EBX = virtual address
  2634                              <1> 	;
  2635                              <1> 	;	CF = 1 -> error
  2636                              <1> 	;
  2637                              <1> 	; Modified Registers -> EAX, EDX
  2638                              <1> 	;
  2639 00002E8A 50                  <1> 	push	eax
  2640 00002E8B A1[AF700000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2641 00002E90 E837000000          <1> 	call 	get_pde
  2642                              <1> 		; EDX = PDE address
  2643                              <1> 		; EAX = PDE value
  2644 00002E95 5A                  <1> 	pop	edx ; physical page address
  2645 00002E96 722A                <1> 	jc	short spte_err ; PDE not present
  2646                              <1> 	;
  2647 00002E98 53                  <1> 	push	ebx ; 24/07/2015
  2648 00002E99 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2649                              <1> 			    ; EDX = PT address (physical)	
  2650 00002E9D C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2651 00002EA0 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2652                              <1> 			 ; clear higher 10 bits (PD bits)
  2653 00002EA6 C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2654 00002EA9 01C3                <1> 	add	ebx, eax
  2655                              <1> 	;
  2656 00002EAB 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2657 00002EAD A801                <1> 	test	al, 1
  2658 00002EAF 740C                <1> 	jz	short spte_0
  2659 00002EB1 09D2                <1> 	or	edx, edx
  2660 00002EB3 750F                <1> 	jnz	short spte_1
  2661 00002EB5 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2662 00002EB9 89C2                <1> 	mov	edx, eax
  2663 00002EBB EB09                <1> 	jmp	short spte_2	
  2664                              <1> spte_0:
  2665                              <1> 	; If this PTE contains a swap (disk) address,
  2666                              <1> 	; it can be updated by using 'swap_in' procedure
  2667                              <1> 	; only!
  2668 00002EBD 21C0                <1> 	and	eax, eax
  2669 00002EBF 7403                <1> 	jz	short spte_1
  2670                              <1> 	; 24/07/2015
  2671                              <1> 	; swapped page ! (on disk)
  2672 00002EC1 5B                  <1> 	pop	ebx
  2673                              <1> spte_err:
  2674 00002EC2 F9                  <1> 	stc
  2675 00002EC3 C3                  <1> 	retn
  2676                              <1> spte_1: 
  2677 00002EC4 89D0                <1> 	mov	eax, edx
  2678                              <1> spte_2:
  2679 00002EC6 09CA                <1> 	or	edx, ecx
  2680                              <1> 	; 23/06/2015
  2681 00002EC8 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2682                              <1> 	; 24/07/2015
  2683 00002ECA 5B                  <1> 	pop	ebx
  2684 00002ECB C3                  <1> 	retn
  2685                              <1> 
  2686                              <1> get_pde:	; Get present value of the relevant PDE
  2687                              <1> 	; 20/07/2015
  2688                              <1> 	; 18/04/2015
  2689                              <1> 	; 12/04/2015
  2690                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2691                              <1> 	;
  2692                              <1> 	; INPUT ->
  2693                              <1> 	;	EBX = virtual (linear) address
  2694                              <1> 	;	EAX = page directory (physical) address
  2695                              <1> 	; OUTPUT ->
  2696                              <1> 	;	EDX = Page directory entry address
  2697                              <1> 	;	EAX = Page directory entry value
  2698                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2699                              <1> 	; Modified Registers -> EDX, EAX
  2700                              <1> 	;
  2701 00002ECC 89DA                <1> 	mov	edx, ebx
  2702 00002ECE C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2703 00002ED1 C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2704 00002ED4 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2705 00002ED6 8B02                <1> 	mov	eax, [edx]
  2706 00002ED8 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2707 00002EDA 751F                <1> 	jnz	short gpte_retn
  2708 00002EDC F9                  <1> 	stc
  2709                              <1> gpde_retn:	
  2710 00002EDD C3                  <1> 	retn
  2711                              <1> 
  2712                              <1> get_pte:
  2713                              <1> 		; Get present value of the relevant PTE
  2714                              <1> 	; 29/07/2015
  2715                              <1> 	; 20/07/2015
  2716                              <1> 	; 18/04/2015
  2717                              <1> 	; 12/04/2015
  2718                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2719                              <1> 	;
  2720                              <1> 	; INPUT ->
  2721                              <1> 	;	EBX = virtual (linear) address
  2722                              <1> 	;	EAX = page directory (physical) address
  2723                              <1> 	; OUTPUT ->
  2724                              <1> 	;	EDX = Page table entry address (if CF=0)
  2725                              <1> 	;	      Page directory entry address (if CF=1)
  2726                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2727                              <1> 	;	EAX = Page table entry value (page address)
  2728                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2729                              <1> 	; Modified Registers -> EAX, EDX
  2730                              <1> 	;
  2731 00002EDE E8E9FFFFFF          <1> 	call 	get_pde
  2732 00002EE3 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2733                              <1> 	;jnc	short gpte_1
  2734                              <1> 	;retn
  2735                              <1> ;gpte_1:
  2736 00002EE5 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2737 00002EE9 89DA                <1> 	mov	edx, ebx
  2738 00002EEB C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2739 00002EEE 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2740                              <1> 			 ; clear higher 10 bits (PD bits)
  2741 00002EF4 C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2742 00002EF7 01C2                <1> 	add	edx, eax
  2743 00002EF9 8B02                <1> 	mov	eax, [edx]
  2744                              <1> gpte_retn:
  2745 00002EFB C3                  <1> 	retn
  2746                              <1> 
  2747                              <1> deallocate_page_dir:
  2748                              <1> 	; 15/09/2015
  2749                              <1> 	; 05/08/2015
  2750                              <1> 	; 30/04/2015
  2751                              <1> 	; 28/04/2015
  2752                              <1> 	; 17/10/2014
  2753                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2754                              <1> 	;
  2755                              <1> 	; INPUT ->
  2756                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2757                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2758                              <1> 	; OUTPUT ->
  2759                              <1> 	;	All of page tables in the page directory
  2760                              <1> 	;	and page dir's itself will be deallocated
  2761                              <1> 	;	except 'read only' duplicated pages (will be converted
  2762                              <1> 	;	to writable pages).
  2763                              <1> 	;
  2764                              <1> 	; Modified Registers -> EAX
  2765                              <1> 	;
  2766                              <1> 	;
  2767 00002EFC 56                  <1> 	push	esi
  2768 00002EFD 51                  <1> 	push	ecx
  2769 00002EFE 50                  <1> 	push	eax
  2770 00002EFF 89C6                <1> 	mov	esi, eax 
  2771 00002F01 31C9                <1> 	xor	ecx, ecx
  2772                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2773                              <1> 	; it must not be deallocated
  2774 00002F03 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2775                              <1> dapd_0:
  2776 00002F05 AD                  <1> 	lodsd
  2777 00002F06 A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2778 00002F08 7409                <1> 	jz	short dapd_1	
  2779 00002F0A 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2780 00002F0E E812000000          <1> 	call	deallocate_page_table			
  2781                              <1> dapd_1:
  2782 00002F13 41                  <1> 	inc	ecx ; page directory entry index
  2783 00002F14 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2784 00002F1A 72E9                <1> 	jb	short dapd_0
  2785                              <1> dapd_2:
  2786 00002F1C 58                  <1> 	pop	eax
  2787 00002F1D E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2788 00002F22 59                  <1> 	pop	ecx
  2789 00002F23 5E                  <1> 	pop	esi
  2790 00002F24 C3                  <1> 	retn
  2791                              <1> 
  2792                              <1> deallocate_page_table:
  2793                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2794                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2795                              <1> 	; 19/09/2015
  2796                              <1> 	; 15/09/2015
  2797                              <1> 	; 05/08/2015
  2798                              <1> 	; 30/04/2015
  2799                              <1> 	; 28/04/2015
  2800                              <1> 	; 24/10/2014
  2801                              <1> 	; 23/10/2014
  2802                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2803                              <1> 	;
  2804                              <1> 	; INPUT ->
  2805                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2806                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2807                              <1> 	;	(ECX = page directory entry index)
  2808                              <1> 	; OUTPUT ->
  2809                              <1> 	;	All of pages in the page table and page table's itself
  2810                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2811                              <1> 	;	(will be converted to writable pages).
  2812                              <1> 	;
  2813                              <1> 	; Modified Registers -> EAX
  2814                              <1> 	;
  2815 00002F25 56                  <1> 	push	esi
  2816 00002F26 57                  <1> 	push	edi
  2817 00002F27 52                  <1> 	push	edx
  2818 00002F28 50                  <1> 	push	eax ; *
  2819 00002F29 89C6                <1> 	mov	esi, eax 
  2820 00002F2B 31FF                <1> 	xor	edi, edi ; 0
  2821                              <1> dapt_0:
  2822 00002F2D AD                  <1> 	lodsd
  2823 00002F2E A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2824 00002F30 7455                <1> 	jz	short dapt_1
  2825                              <1> 	;
  2826 00002F32 A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2827                              <1> 				  ; (must be 1)
  2828 00002F34 753F                <1> 	jnz	short dapt_3
  2829                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2830 00002F36 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2831                              <1> 				   ; as child's page ?
  2832 00002F3A 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2833                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2834                              <1> 	; ECX = page directory entry index (0-1023)
  2835 00002F3C 53                  <1> 	push	ebx
  2836 00002F3D 51                  <1> 	push	ecx
  2837 00002F3E 66C1E102            <1> 	shl	cx, 2 ; *4 
  2838 00002F42 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2839 00002F44 8B0B                <1> 	mov	ecx, [ebx]
  2840 00002F46 F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2841 00002F49 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2842 00002F4B 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2843                              <1> 	; EDI = page table entry index (0-1023)
  2844 00002F50 89FA                <1> 	mov	edx, edi 
  2845 00002F52 66C1E202            <1> 	shl	dx, 2 ; *4 
  2846 00002F56 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2847 00002F58 8B1A                <1> 	mov	ebx, [edx]
  2848 00002F5A F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2849 00002F5D 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2850 00002F5F 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2851 00002F63 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2852 00002F68 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2853 00002F6A 7507                <1> 	jne	short dapt_2	; not same page
  2854                              <1> 				; deallocate the child's page
  2855 00002F6C 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2856 00002F6F 59                  <1> 	pop	ecx
  2857 00002F70 5B                  <1> 	pop	ebx
  2858 00002F71 EB0D                <1> 	jmp	short dapt_4
  2859                              <1> 
  2860                              <1> ; 24/12/2021
  2861                              <1> ; ('dapt_1' is disabled)
  2862                              <1> ;
  2863                              <1> ;dapt_1:
  2864                              <1> ;	or	eax, eax	; swapped page ?
  2865                              <1> ;	jz	short dapt_5	; no
  2866                              <1> ;				; yes
  2867                              <1> ;	shr	eax, 1
  2868                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2869                              <1> ;				  ; on the swap disk (or in file)
  2870                              <1> ;	jmp	short dapt_5
  2871                              <1> dapt_2:
  2872 00002F73 59                  <1> 	pop	ecx
  2873 00002F74 5B                  <1> 	pop	ebx
  2874                              <1> dapt_3:	
  2875                              <1> 	; 12/07/2016
  2876 00002F75 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2877 00002F79 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2878                              <1> 	;
  2879                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2880 00002F7B E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2881                              <1> dapt_4:
  2882 00002F80 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2883                              <1> dapt_1:	; 24/12/2021
  2884                              <1> dapt_5:
  2885 00002F87 47                  <1> 	inc	edi ; page table entry index
  2886 00002F88 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2887 00002F8E 729D                <1> 	jb	short dapt_0
  2888                              <1> 	;
  2889 00002F90 58                  <1> 	pop	eax ; *
  2890 00002F91 5A                  <1> 	pop	edx
  2891 00002F92 5F                  <1> 	pop	edi	
  2892 00002F93 5E                  <1> 	pop	esi
  2893                              <1> 	;
  2894                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2895                              <1> 	;retn
  2896                              <1> 
  2897                              <1> deallocate_page:
  2898                              <1> 	; 15/09/2015
  2899                              <1> 	; 28/04/2015
  2900                              <1> 	; 10/03/2015
  2901                              <1> 	; 17/10/2014
  2902                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2903                              <1> 	;
  2904                              <1> 	; INPUT -> 
  2905                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2906                              <1> 	; OUTPUT ->
  2907                              <1> 	;	[free_pages] is increased
  2908                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2909                              <1> 	;	CF = 1 if the page is already deallocated
  2910                              <1> 	; 	       (or not allocated) before.  
  2911                              <1> 	;
  2912                              <1> 	; Modified Registers -> EAX
  2913                              <1> 	;
  2914 00002F94 53                  <1> 	push	ebx
  2915 00002F95 52                  <1> 	push	edx
  2916                              <1> 	;
  2917 00002F96 C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2918                              <1> 				     ; 12 bits right
  2919                              <1> 				     ; to get page number
  2920 00002F99 89C2                <1> 	mov	edx, eax
  2921                              <1> 	; 15/09/2015
  2922 00002F9B C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2923                              <1> 				     ; (1 allocation bit = 1 page)
  2924                              <1> 				     ; (1 allocation bytes = 8 pages)
  2925 00002F9E 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2926                              <1> 				     ; (to get 32 bit position)			
  2927                              <1> 	;
  2928 00002FA1 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2929 00002FA6 01D3                <1> 	add	ebx, edx
  2930 00002FA8 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2931                              <1> 				     ; (allocation bit position)	 
  2932 00002FAB 3B15[A46C0000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2933                              <1> 				     ; than the address in 'next_page' ?
  2934                              <1> 				     ; (next/first free page value)		
  2935 00002FB1 7306                <1> 	jnb	short dap_1	     ; no	
  2936 00002FB3 8915[A46C0000]      <1> 	mov	[next_page], edx     ; yes
  2937                              <1> dap_1:
  2938 00002FB9 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2939                              <1> 				     ; set relevant bit to 1.
  2940                              <1> 				     ; set CF to the previous bit value	
  2941                              <1> 	;cmc			     ; complement carry flag	
  2942                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2943                              <1> 				     ; if the page is already deallocated
  2944                              <1> 				     ; before.	
  2945 00002FBC FF05[A06C0000]      <1>         inc     dword [free_pages]
  2946                              <1> dap_2:
  2947 00002FC2 5A                  <1> 	pop	edx
  2948 00002FC3 5B                  <1> 	pop	ebx
  2949 00002FC4 C3                  <1> 	retn
  2950                              <1> 
  2951                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2952                              <1> ;;                                                              ;;
  2953                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2954                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2955                              <1> ;;                                                              ;;
  2956                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2957                              <1> 
  2958                              <1> ;;$Revision: 5057 $
  2959                              <1> 
  2960                              <1> 
  2961                              <1> ;;align 4
  2962                              <1> ;;proc alloc_page
  2963                              <1> 
  2964                              <1> ;;        pushfd
  2965                              <1> ;;        cli
  2966                              <1> ;;        push    ebx
  2967                              <1> ;;;//-
  2968                              <1> ;;        cmp     [pg_data.pages_free], 1
  2969                              <1> ;;        jle     .out_of_memory
  2970                              <1> ;;;//-
  2971                              <1> ;;
  2972                              <1> ;;        mov     ebx, [page_start]
  2973                              <1> ;;        mov     ecx, [page_end]
  2974                              <1> ;;.l1:
  2975                              <1> ;;        bsf     eax, [ebx];
  2976                              <1> ;;        jnz     .found
  2977                              <1> ;;        add     ebx, 4
  2978                              <1> ;;        cmp     ebx, ecx
  2979                              <1> ;;        jb      .l1
  2980                              <1> ;;        pop     ebx
  2981                              <1> ;;        popfd
  2982                              <1> ;;        xor     eax, eax
  2983                              <1> ;;        ret
  2984                              <1> ;;.found:
  2985                              <1> ;;;//-
  2986                              <1> ;;        dec     [pg_data.pages_free]
  2987                              <1> ;;        jz      .out_of_memory
  2988                              <1> ;;;//-
  2989                              <1> ;;        btr     [ebx], eax
  2990                              <1> ;;        mov     [page_start], ebx
  2991                              <1> ;;        sub     ebx, sys_pgmap
  2992                              <1> ;;        lea     eax, [eax+ebx*8]
  2993                              <1> ;;        shl     eax, 12
  2994                              <1> ;;;//-       dec [pg_data.pages_free]
  2995                              <1> ;;        pop     ebx
  2996                              <1> ;;        popfd
  2997                              <1> ;;        ret
  2998                              <1> ;;;//-
  2999                              <1> ;;.out_of_memory:
  3000                              <1> ;;        mov     [pg_data.pages_free], 1
  3001                              <1> ;;        xor     eax, eax
  3002                              <1> ;;        pop     ebx
  3003                              <1> ;;        popfd
  3004                              <1> ;;        ret
  3005                              <1> ;;;//-
  3006                              <1> ;;endp
  3007                              <1> 
  3008                              <1> duplicate_page_dir:
  3009                              <1> 	; 21/09/2015
  3010                              <1> 	; 31/08/2015
  3011                              <1> 	; 20/07/2015
  3012                              <1> 	; 28/04/2015
  3013                              <1> 	; 27/04/2015
  3014                              <1> 	; 18/04/2015
  3015                              <1> 	; 12/04/2015
  3016                              <1> 	; 18/10/2014
  3017                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3018                              <1> 	;
  3019                              <1> 	; INPUT -> 
  3020                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3021                              <1> 	;		    page directory.
  3022                              <1> 	; OUTPUT ->
  3023                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3024                              <1> 	;	       page directory.
  3025                              <1> 	;	(New page directory with new page table entries.)
  3026                              <1> 	;	(New page tables with read only copies of the parent's
  3027                              <1> 	;	pages.)
  3028                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3029                              <1> 	;
  3030                              <1> 	; Modified Registers -> none (except EAX)
  3031                              <1> 	;
  3032 00002FC5 E802FEFFFF          <1> 	call	allocate_page
  3033 00002FCA 723E                <1> 	jc	short dpd_err
  3034                              <1> 	;
  3035 00002FCC 55                  <1> 	push	ebp ; 20/07/2015
  3036 00002FCD 56                  <1> 	push	esi
  3037 00002FCE 57                  <1> 	push	edi
  3038 00002FCF 53                  <1> 	push	ebx
  3039 00002FD0 51                  <1> 	push	ecx
  3040 00002FD1 8B35[AF700000]      <1> 	mov	esi, [u.pgdir]
  3041 00002FD7 89C7                <1> 	mov	edi, eax
  3042 00002FD9 50                  <1> 	push	eax ; save child's page directory address
  3043                              <1> 	; 31/08/2015
  3044                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3045                              <1> 	; (use same system space for all user page tables) 
  3046 00002FDA A5                  <1> 	movsd
  3047 00002FDB BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3048 00002FE0 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3049                              <1> dpd_0:	
  3050 00002FE5 AD                  <1> 	lodsd
  3051                              <1> 	;or	eax, eax
  3052                              <1>         ;jnz     short dpd_1
  3053 00002FE6 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3054 00002FE8 7508                <1> 	jnz	short dpd_1
  3055                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3056 00002FEA 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3057 00002FF0 EB0F                <1> 	jmp	short dpd_2
  3058                              <1> dpd_1:	
  3059 00002FF2 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3060 00002FF6 89C3                <1> 	mov	ebx, eax
  3061                              <1> 	; EBX = Parent's page table address
  3062 00002FF8 E81F000000          <1> 	call	duplicate_page_table
  3063 00002FFD 720C                <1> 	jc	short dpd_p_err
  3064                              <1> 	; EAX = Child's page table address
  3065 00002FFF 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3066                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3067                              <1> 			 ; (present, writable, user)
  3068                              <1> dpd_2:
  3069 00003001 AB                  <1> 	stosd
  3070 00003002 E2E1                <1> 	loop	dpd_0
  3071                              <1> 	;
  3072 00003004 58                  <1> 	pop	eax  ; restore child's page directory address
  3073                              <1> dpd_3:
  3074 00003005 59                  <1> 	pop	ecx
  3075 00003006 5B                  <1> 	pop	ebx
  3076 00003007 5F                  <1> 	pop	edi
  3077 00003008 5E                  <1> 	pop	esi
  3078 00003009 5D                  <1> 	pop	ebp ; 20/07/2015
  3079                              <1> dpd_err:
  3080 0000300A C3                  <1> 	retn
  3081                              <1> dpd_p_err:
  3082                              <1> 	; release the allocated pages missing (recover free space)
  3083 0000300B 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3084 0000300C 8B1D[AF700000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3085 00003012 E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3086 00003017 29C0                <1> 	sub	eax, eax ; 0
  3087 00003019 F9                  <1> 	stc
  3088 0000301A EBE9                <1> 	jmp	short dpd_3	
  3089                              <1> 
  3090                              <1> duplicate_page_table:
  3091                              <1> 	; 31/12/2021
  3092                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3093                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3094                              <1> 	; 21/09/2015
  3095                              <1> 	; 20/07/2015
  3096                              <1> 	; 05/05/2015
  3097                              <1> 	; 28/04/2015
  3098                              <1> 	; 27/04/2015
  3099                              <1> 	; 18/04/2015
  3100                              <1> 	; 18/10/2014
  3101                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3102                              <1> 	;
  3103                              <1> 	; INPUT -> 
  3104                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3105                              <1> 	;       20/02/2017		 
  3106                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3107                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3108                              <1> 	; OUTPUT ->
  3109                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3110                              <1> 	;	      (with 'read only' attribute of page table entries)
  3111                              <1> 	;	20/02/2017
  3112                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3113                              <1> 	;	
  3114                              <1> 	;	CF = 1 -> error 
  3115                              <1> 	;
  3116                              <1> 	; Modified Registers -> EBP (except EAX)
  3117                              <1> 	;
  3118 0000301C E8ABFDFFFF          <1> 	call	allocate_page
  3119 00003021 725B                <1> 	jc	short dpt_err
  3120                              <1> 	;
  3121 00003023 50                  <1> 	push	eax ; *
  3122 00003024 56                  <1> 	push	esi
  3123 00003025 57                  <1> 	push	edi
  3124 00003026 52                  <1> 	push	edx
  3125 00003027 51                  <1> 	push	ecx
  3126                              <1> 	;
  3127 00003028 89DE                <1> 	mov	esi, ebx
  3128 0000302A 89C7                <1> 	mov	edi, eax
  3129 0000302C 89C2                <1> 	mov	edx, eax
  3130 0000302E 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3131                              <1> dpt_0:
  3132 00003034 AD                  <1> 	lodsd
  3133 00003035 21C0                <1> 	and	eax, eax
  3134 00003037 7435                <1> 	jz	short dpt_3
  3135 00003039 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3136                              <1> 	; 24/12/2021
  3137 0000303B 7503                <1> 	jnz	short dpt_1
  3138                              <1> 	;jz	short dpt_p_err
  3139                              <1> 	; 31/12/2021
  3140 0000303D F9                  <1> 	stc
  3141 0000303E EB39                <1> 	jmp	short dpt_p_err
  3142                              <1> 
  3143                              <1> ; 24/12/2021
  3144                              <1> ; ('reload_page' procedure call is disabled)
  3145                              <1> ;
  3146                              <1> ;	; 20/07/2015
  3147                              <1> ;	; ebp = virtual (linear) address of the memory page
  3148                              <1> ;	call	reload_page ; 28/04/2015
  3149                              <1> ;	jc	short dpt_p_err
  3150                              <1> dpt_1:
  3151                              <1> 	; 21/09/2015
  3152 00003040 89C1                <1> 	mov	ecx, eax
  3153 00003042 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3154 00003046 F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3155 00003049 751A                <1> 	jnz	short dpt_2
  3156                              <1> 	; Read only (parent) page
  3157                              <1> 	; 	- there is a third process which uses this page -
  3158                              <1> 	; Allocate a new page for the child process
  3159 0000304B E87CFDFFFF          <1> 	call	allocate_page
  3160 00003050 7227                <1> 	jc	short dpt_p_err
  3161 00003052 57                  <1> 	push	edi
  3162 00003053 56                  <1> 	push	esi
  3163 00003054 89CE                <1> 	mov	esi, ecx
  3164 00003056 89C7                <1> 	mov	edi, eax
  3165 00003058 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3166 0000305D F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3167 0000305F 5E                  <1> 	pop	esi
  3168 00003060 5F                  <1> 	pop	edi
  3169                              <1> 	;
  3170                              <1> 
  3171                              <1> ; 24/12/2021
  3172                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3173                              <1> ; 
  3174                              <1> ;	push	ebx
  3175                              <1> ;	push	eax
  3176                              <1> ;	; 20/07/2015
  3177                              <1> ;	mov	ebx, ebp
  3178                              <1> ;	; ebx = virtual (linear) address of the memory page
  3179                              <1> ;	call	add_to_swap_queue
  3180                              <1> ;	pop	eax
  3181                              <1> ;	pop	ebx
  3182                              <1> 
  3183                              <1> 	; 21/09/2015
  3184 00003061 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3185                              <1> 		; user + writable + present page
  3186 00003063 EB09                <1> 	jmp	short dpt_3
  3187                              <1> dpt_2:
  3188                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3189 00003065 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3190                              <1> 		    ; (read only page!)
  3191 00003067 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3192 0000306A 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3193                              <1> dpt_3:
  3194 0000306E AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3195                              <1> 	;
  3196 0000306F 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3197                              <1> 	;
  3198 00003075 39D7                <1> 	cmp	edi, edx
  3199 00003077 72BB                <1> 	jb	short dpt_0
  3200                              <1> dpt_p_err:
  3201 00003079 59                  <1> 	pop	ecx
  3202 0000307A 5A                  <1> 	pop	edx
  3203 0000307B 5F                  <1> 	pop	edi
  3204 0000307C 5E                  <1> 	pop	esi
  3205 0000307D 58                  <1> 	pop	eax ; *
  3206                              <1> dpt_err:
  3207 0000307E C3                  <1> 	retn
  3208                              <1> 
  3209                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3210                              <1> 	; 31/12/2021
  3211                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3212                              <1> 	; 21/09/2015
  3213                              <1> 	; 19/09/2015
  3214                              <1> 	; 17/09/2015
  3215                              <1> 	; 28/08/2015
  3216                              <1> 	; 20/07/2015
  3217                              <1> 	; 28/06/2015
  3218                              <1> 	; 03/05/2015
  3219                              <1> 	; 30/04/2015
  3220                              <1> 	; 18/04/2015
  3221                              <1> 	; 12/04/2015
  3222                              <1> 	; 30/10/2014
  3223                              <1> 	; 11/09/2014
  3224                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3225                              <1> 	;
  3226                              <1> 	; Note: This is not an interrupt/exception handler.
  3227                              <1> 	;	This is a 'page fault remedy' subroutine 
  3228                              <1> 	;	which will be called by standard/uniform
  3229                              <1> 	;	exception handler.
  3230                              <1> 	;
  3231                              <1> 	; INPUT -> 
  3232                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3233                              <1> 	;
  3234                              <1> 	;	cr2 = the virtual (linear) address 
  3235                              <1> 	;	      which has caused to page fault (19/09/2015)
  3236                              <1> 	;
  3237                              <1> 	; OUTPUT ->
  3238                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3239                              <1> 	;	EAX = 0 -> no error
  3240                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3241                              <1> 	;
  3242                              <1> 	; Modified Registers -> none (except EAX)
  3243                              <1> 	;	
  3244                              <1>         ;
  3245                              <1>         ; ERROR CODE:
  3246                              <1> 	;	 31  .....	4   3	2   1	0
  3247                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3248                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3249                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3250                              <1> 	;
  3251                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3252                              <1>     	;		a page-protection violation. When not set,
  3253                              <1> 	;		it was caused by a non-present page.
  3254                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3255                              <1> 	;		a page write. When not set, it was caused
  3256                              <1> 	;		by a page read.
  3257                              <1> 	; U : USER    -	When set, the page fault was caused 
  3258                              <1> 	;		while CPL = 3. 
  3259                              <1> 	;		This does not necessarily mean that
  3260                              <1> 	;		the page fault was a privilege violation.
  3261                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3262                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3263                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3264                              <1> 	;     FETCH	an instruction fetch
  3265                              <1> 	;
  3266                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3267                              <1> 	;  31               22                  12 11                    0
  3268                              <1> 	; +-------------------+-------------------+-----------------------+
  3269                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3270                              <1>        	; +-------------------+-------------------+-----------------------+
  3271                              <1> 	;
  3272                              <1> 
  3273                              <1> 	;; CR3 REGISTER (Control Register 3)
  3274                              <1> 	;  31                                   12             5 4 3 2   0
  3275                              <1> 	; +---------------------------------------+-------------+---+-----+
  3276                              <1>       	; |                                       |  		|P|P|     |
  3277                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3278                              <1>       	; |                                       | 		|D|T|     |
  3279                              <1>    	; +---------------------------------------+-------------+---+-----+
  3280                              <1> 	;
  3281                              <1> 	;	PWT    - WRITE THROUGH
  3282                              <1> 	;	PCD    - CACHE DISABLE		
  3283                              <1> 	;
  3284                              <1> 	;
  3285                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3286                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3287                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3288                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3289                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3290                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3291                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3292                              <1> 	;
  3293                              <1>         ;       P      - PRESENT
  3294                              <1>         ;       R/W    - READ/WRITE
  3295                              <1>         ;       U/S    - USER/SUPERVISOR
  3296                              <1> 	;	PWT    - WRITE THROUGH
  3297                              <1> 	;	PCD    - CACHE DISABLE	
  3298                              <1> 	;	A      - ACCESSED	
  3299                              <1>         ;       D      - DIRTY (IGNORED)
  3300                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3301                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3302                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3303                              <1> 	;
  3304                              <1> 	;
  3305                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3306                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3307                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3308                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3309                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3310                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3311                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3312                              <1> 	;
  3313                              <1>         ;       P      - PRESENT
  3314                              <1>         ;       R/W    - READ/WRITE
  3315                              <1>         ;       U/S    - USER/SUPERVISOR
  3316                              <1> 	;	PWT    - WRITE THROUGH
  3317                              <1> 	;	PCD    - CACHE DISABLE	
  3318                              <1> 	;	A      - ACCESSED	
  3319                              <1>         ;       D      - DIRTY
  3320                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3321                              <1> 	;	G      - GLOBAL	 
  3322                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3323                              <1> 	;
  3324                              <1> 	;
  3325                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3326                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3327                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3328                              <1>       	; |                                       |     | | | | | | |U|R| |
  3329                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3330                              <1>       	; |                                       |     | | | | | | |S|W| |
  3331                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3332                              <1> 	;
  3333                              <1>         ;       P      - PRESENT
  3334                              <1>         ;       R/W    - READ/WRITE
  3335                              <1>         ;       U/S    - USER/SUPERVISOR
  3336                              <1>         ;       D      - DIRTY
  3337                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3338                              <1> 	;
  3339                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3340                              <1> 	;
  3341                              <1> 	;
  3342                              <1> 	;; Invalid Page Table Entry
  3343                              <1> 	; 31                                                           1 0
  3344                              <1>       	; +-------------------------------------------------------------+-+
  3345                              <1>       	; |                                                             | |
  3346                              <1>       	; |                          AVAILABLE                          |0|
  3347                              <1>       	; |                                                             | |
  3348                              <1>       	; +-------------------------------------------------------------+-+
  3349                              <1> 	;
  3350                              <1> 
  3351 0000307F 53                  <1> 	push	ebx
  3352 00003080 52                  <1> 	push	edx
  3353 00003081 51                  <1> 	push	ecx
  3354                              <1> 	;
  3355                              <1> 	; 21/09/2015 (debugging)
  3356 00003082 FF05[BF700000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3357 00003088 FF05[506D0000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3358                              <1> 	; 28/06/2015
  3359                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3360 0000308E 8A15[486D0000]      <1> 	mov	dl, [error_code]
  3361                              <1> 	;
  3362 00003094 F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3363                              <1> 			; sign
  3364 00003097 7425                <1> 	jz	short pfh_alloc_np
  3365                              <1> 	; 
  3366                              <1> 	; If it is not a 'write on read only page' type page fault
  3367                              <1> 	; major page fault error with minor reason must be returned without 
  3368                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3369                              <1> 	; after return here!
  3370                              <1> 	; Page fault will be remedied, by copying page contents
  3371                              <1> 	; to newly allocated page with write permission;
  3372                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3373                              <1> 	; used for working with minimum possible memory usage. 
  3374                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3375                              <1> 	; process with 'read only' flag. If the child process attempts to
  3376                              <1> 	; write on these read only pages, page fault will be directed here
  3377                              <1> 	; for allocating a new page with same data/content. 
  3378                              <1> 	;
  3379                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3380                              <1> 	; will not force to separate CODE and DATA space 
  3381                              <1> 	; in a process/program... 
  3382                              <1> 	; CODE segment/section may contain DATA!
  3383                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3384                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3385                              <1> 	;	
  3386 00003099 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3387                              <1> 			; sign
  3388 0000309C 7418                <1>         jz      pfh_p_err
  3389                              <1> 	; 31/08/2015
  3390 0000309E F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3391                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3392 000030A1 7413                <1>         jz	short pfh_pv_err
  3393                              <1> 	;
  3394                              <1> 	; make a new page and copy the parent's page content
  3395                              <1> 	; as the child's new page content
  3396                              <1> 	;
  3397 000030A3 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3398                              <1> 			 ; which has caused to page fault
  3399 000030A6 E87C000000          <1> 	call 	copy_page
  3400 000030AB 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3401                              <1> 	;
  3402 000030AD EB72                <1>         jmp     pfh_cpp_ok
  3403                              <1> 
  3404                              <1> 	; 31/12/2021 (short jump)
  3405                              <1> pfh_im_err:
  3406 000030AF B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3407                              <1> 			; Major (Primary) Error: Page Fault
  3408                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3409 000030B4 EB6D                <1> 	jmp	short pfh_err_retn
  3410                              <1> 
  3411                              <1> 	; 31/12/2021
  3412                              <1> pfh_p_err: ; 09/03/2015
  3413                              <1> pfh_pv_err:
  3414                              <1> 	; Page fault was caused by a protection-violation
  3415 000030B6 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3416                              <1> 			; Major (Primary) Error: Page Fault
  3417                              <1> 			; Minor (Secondary) Error: Protection violation !
  3418 000030BB F9                  <1> 	stc
  3419 000030BC EB65                <1> 	jmp	short pfh_err_retn
  3420                              <1> 	
  3421                              <1> pfh_alloc_np:
  3422 000030BE E809FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3423 000030C3 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3424                              <1> pfh_chk_cpl:
  3425                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3426                              <1> 		; (Lower 12 bits are ZERO, because 
  3427                              <1> 		;	the address is on a page boundary)
  3428 000030C5 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3429 000030C8 7505                <1> 	jnz	short pfh_um
  3430                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3431 000030CA 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3432                              <1> 			 ; of the current/active page directory
  3433                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3434                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3435 000030CD EB06                <1> 	jmp	short pfh_get_pde
  3436                              <1> 	;
  3437                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3438 000030CF 8B1D[AF700000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3439                              <1> 			; Physical address of the USER's page directory
  3440                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3441                              <1> pfh_get_pde:
  3442 000030D5 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3443 000030D8 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3444                              <1> 			 ; which has been caused to page fault
  3445                              <1> 			 ;
  3446 000030DB C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3447 000030DE 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3448                              <1> 	;
  3449 000030E1 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3450 000030E3 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3451 000030E5 F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3452 000030E8 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3453                              <1> 			  	  ; set/validate page directory entry
  3454 000030EA 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3455 000030EF 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3456 000030F1 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3457 000030F3 EB16                <1> 	jmp	short pfh_get_pte
  3458                              <1> pfh_set_pde:
  3459                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3460                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3461                              <1> 	;
  3462 000030F5 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3463 000030F7 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3464 000030F9 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3465 000030FB 89C3                <1> 	mov	ebx, eax
  3466 000030FD E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3467 00003102 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3468                              <1> pfh_spde_1:
  3469                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3470 00003104 89C1                <1> 	mov	ecx, eax
  3471 00003106 E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3472                              <1> pfh_get_pte:
  3473 0000310B 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3474                              <1> 			 ; which has been caused to page fault
  3475 0000310E 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3476 00003110 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3477                              <1> 			 ; higher 20 bits of the page fault address 
  3478 00003113 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3479 00003118 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3480 0000311B 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3481                              <1> ; 24/12/2021
  3482                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3483                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3484                              <1> ; 24/12/2021
  3485                              <1> ; ('swap_in' procedure call has been disabled)
  3486                              <1> ;
  3487                              <1> ;	and	eax, eax
  3488                              <1> ;	jz	short pfh_gpte_1
  3489                              <1> ;	; 20/07/2015
  3490                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3491                              <1> ;	push	ebp ; 20/07/2015
  3492                              <1> ;	mov	ebp, cr2
  3493                              <1> ;		; ECX = physical address of the page table entry
  3494                              <1> ;		; EBX = Memory page address (physical!)
  3495                              <1> ;		; EAX = Swap disk (offset) address
  3496                              <1> ;		; EBP = virtual address (page fault address)
  3497                              <1> ;	call	swap_in
  3498                              <1> ;	pop	ebp
  3499                              <1> ;	jc      short pfh_err_retn
  3500                              <1> ;	xchg	ecx, ebx
  3501                              <1> ;		; EBX = physical address of the page table entry
  3502                              <1> ;		; ECX = new page
  3503                              <1> pfh_gpte_1:
  3504 0000311D 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3505 0000311F 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3506                              <1> pfh_cpp_ok:
  3507                              <1> ; 24/12/2021
  3508                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3509                              <1> ;
  3510                              <1> ;	; 20/07/2015
  3511                              <1> ;	mov	ebx, cr2
  3512                              <1> ;	call 	add_to_swap_queue
  3513                              <1> 	;
  3514                              <1> 	; The new PTE (which contains the new page) will be added to 
  3515                              <1> 	; the swap queue, here. 
  3516                              <1> 	; (Later, if memory will become insufficient, 
  3517                              <1> 	; one page will be swapped out which is at the head of 
  3518                              <1> 	; the swap queue by using FIFO and access check methods.)
  3519                              <1> 	;
  3520 00003121 31C0                <1> 	xor	eax, eax  ; 0
  3521                              <1> 	;
  3522                              <1> pfh_err_retn:
  3523 00003123 59                  <1> 	pop	ecx
  3524 00003124 5A                  <1> 	pop	edx
  3525 00003125 5B                  <1> 	pop	ebx
  3526 00003126 C3                  <1> 	retn 
  3527                              <1> 	
  3528                              <1> copy_page:
  3529                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3530                              <1> 	; 16/04/2021
  3531                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3532                              <1> 	; 22/09/2015
  3533                              <1> 	; 21/09/2015
  3534                              <1> 	; 19/09/2015
  3535                              <1> 	; 07/09/2015
  3536                              <1> 	; 31/08/2015
  3537                              <1> 	; 20/07/2015
  3538                              <1> 	; 05/05/2015
  3539                              <1> 	; 03/05/2015
  3540                              <1> 	; 18/04/2015
  3541                              <1> 	; 12/04/2015
  3542                              <1> 	; 30/10/2014
  3543                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3544                              <1> 	;
  3545                              <1> 	; INPUT -> 
  3546                              <1> 	;	EBX = Virtual (linear) address of source page
  3547                              <1> 	;	     (Page fault address)
  3548                              <1> 	; OUTPUT ->
  3549                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3550                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3551                              <1> 	;	EAX = 0 (CF = 1) 
  3552                              <1> 	;		if there is not a free page to be allocated
  3553                              <1> 	;	(page content of the source page will be copied
  3554                              <1> 	;	onto the target/new page) 	
  3555                              <1> 	;
  3556                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3557                              <1> 	;
  3558                              <1> 
  3559                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3560                              <1> 	; INPUT: 
  3561                              <1> 	;	EBX = Virtual (linear) address of source page
  3562                              <1> 	;	     (Page fault address)
  3563                              <1> 	; OUTPUT:
  3564                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3565                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3566                              <1> 	;	EAX = 0 (CF = 1) 
  3567                              <1> 	;		if there is not a free page to be allocated
  3568                              <1> 	;	(page content of the source page will be copied
  3569                              <1> 	;	onto the target/new page) 	
  3570                              <1> 	;
  3571                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3572                              <1> 	
  3573 00003127 56                  <1> 	push	esi ; *
  3574 00003128 57                  <1> 	push	edi ; **
  3575                              <1> 	; 16/04/2021
  3576                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3577                              <1> 	;push	ebx ; ***
  3578                              <1> 	;push	ecx ; ****
  3579 00003129 31F6                <1> 	xor 	esi, esi
  3580 0000312B C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3581 0000312E 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3582 00003130 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3583 00003133 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3584 00003136 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3585 00003138 031D[AF700000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3586 0000313E 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3587 00003140 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3588 00003144 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3589 00003146 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3590 0000314C 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3591 00003150 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3592                              <1> 	; 07/09/2015
  3593 00003152 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3594                              <1> 				     ; read only page as a child process?)	
  3595 00003157 7509                <1> 	jnz	short cpp_0 ; yes
  3596 00003159 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3597 0000315B 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3598 00003160 EB32                <1> 	jmp	short cpp_1
  3599                              <1> cpp_0:
  3600 00003162 89FE                <1> 	mov	esi, edi
  3601 00003164 0335[B3700000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3602 0000316A 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3603 0000316C 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3604 00003170 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3605 00003172 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3606 00003178 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3607 0000317C 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3608 0000317E 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3609                              <1> 	; 21/09/2015
  3610 00003180 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3611 00003182 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3612                              <1> 	;
  3613 00003186 F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3614 00003189 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3615                              <1> 	;
  3616 0000318B 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3617 00003190 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3618 00003192 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3619                              <1> 			    ; Convert child's page to writable page
  3620                              <1> cpp_1:
  3621 00003194 E833FCFFFF          <1> 	call	allocate_page
  3622 00003199 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3623 0000319B 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3624 0000319D 7405                <1> 	jz	short cpp_2
  3625                              <1> 		; Convert read only page to writable page 
  3626                              <1> 		;(for the parent of the current process)
  3627                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3628                              <1> 	; 22/09/2015
  3629 0000319F 890E                <1> 	mov	[esi], ecx
  3630 000031A1 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3631                              <1> 				 ; 1+2+4 = 7
  3632                              <1> cpp_2:
  3633 000031A4 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3634                              <1> 	; 07/09/2015
  3635 000031A6 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3636 000031A8 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3637 000031AD F3A5                <1> 	rep	movsd ; 31/08/2015
  3638                              <1> cpp_3:		
  3639 000031AF 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3640 000031B1 8903                <1> 	mov	[ebx], eax ; Update PTE
  3641 000031B3 28C0                <1> 	sub	al, al ; clear attributes
  3642                              <1> cpp_4:
  3643                              <1> 	; 16/04/2021
  3644                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3645                              <1> 	;pop	ecx ; ****
  3646                              <1> 	;pop	ebx ; ***
  3647 000031B5 5F                  <1> 	pop	edi ; **
  3648 000031B6 5E                  <1> 	pop	esi ; *
  3649 000031B7 C3                  <1> 	retn
  3650                              <1> 
  3651                              <1> ;; 28/04/2015
  3652                              <1> ;; 24/10/2014
  3653                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3654                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3655                              <1> ;;
  3656                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3657                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3658                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3659                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3660                              <1> ;;
  3661                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3662                              <1> ;;
  3663                              <1> ;; Method:
  3664                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3665                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3666                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3667                              <1> ;;	When a new page is being allocated, swap queue is updated
  3668                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3669                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3670                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3671                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3672                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3673                              <1> ;;	offset value becomes it's previous offset value - 4.
  3674                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3675                              <1> ;;	the queue/list is not shifted.
  3676                              <1> ;;	After the queue/list shift, newly allocated page is added
  3677                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3678                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3679                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3680                              <1> ;;	
  3681                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3682                              <1> ;;	the first non-accessed, writable page in the list, 
  3683                              <1> ;;	from the head to the tail. The list is shifted to left 
  3684                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3685                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3686                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3687                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3688                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3689                              <1> ;;	procedure will be failed)...
  3690                              <1> ;;
  3691                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3692                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3693                              <1> ;;	(PTE) will be added to the tail of the queue after
  3694                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3695                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3696                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3697                              <1> ;;
  3698                              <1> ;;
  3699                              <1> ;;	
  3700                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3701                              <1> ;;
  3702                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3703                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3704                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3705                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3706                              <1> ;;
  3707                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3708                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3709                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3710                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3711                              <1> ;; 		 (entire swap space must be accessed by using
  3712                              <1> ;;		 31 bit offset address) 
  3713                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3714                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3715                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3716                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3717                              <1> ;;
  3718                              <1> ;; 					
  3719                              <1> ;; Method:
  3720                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3721                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3722                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3723                              <1> ;;	Swapping out is performed by using swap page queue.
  3724                              <1> ;;
  3725                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3726                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3727                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3728                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3729                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3730                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3731                              <1> ;;	calculated by adding offset value to the swap partition's 
  3732                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3733                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3734                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3735                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3736                              <1> ;;	is in a partitioned virtual hard disk.) 
  3737                              <1> ;;
  3738                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3739                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3740                              <1> ;;
  3741                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3742                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3743                              <1> ;;
  3744                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3745                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3746                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3747                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3748                              <1> ;;	it means relevant (respective) block is in use, and, 
  3749                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3750                              <1> ;;      swap disk/file block is free.
  3751                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3752                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3753                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3754                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3755                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3756                              <1> ;;	------------------------------------------------------------
  3757                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3758                              <1> ;;	------------------------------------------------------------
  3759                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3760                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3761                              <1> ;;
  3762                              <1> ;;	..............................................................
  3763                              <1> ;;
  3764                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3765                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3766                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3767                              <1> ;;	position with value of 1 on the table is converted to swap
  3768                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3769                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3770                              <1> ;;	number of physical swap disk or virtual swap disk)
  3771                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3772                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3773                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3774                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3775                              <1> ;;	If disk write procedure returns with error or free count of 
  3776                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3777                              <1> ;;	'insufficient memory error' (cf=1). 
  3778                              <1> ;;
  3779                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3780                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3781                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3782                              <1> ;;	free blocks after a disk write error. It will return to 
  3783                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3784                              <1> ;;
  3785                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3786                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3787                              <1> ;;	address (cf=0). 
  3788                              <1> ;;
  3789                              <1> ;;	..............................................................
  3790                              <1> ;;
  3791                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3792                              <1> ;;	file sectors at specified memory page. Then page allocation
  3793                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3794                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3795                              <1> ;;	to do, except to terminate the process which is the owner of
  3796                              <1> ;;	the swapped page.
  3797                              <1> ;;
  3798                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3799                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3800                              <1> ;;	updates [swpd_first] pointer if it is required.
  3801                              <1> ;;
  3802                              <1> ;;	..............................................................	 
  3803                              <1> ;;
  3804                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3805                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3806                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3807                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3808                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3809                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3810                              <1> ;;
  3811                              <1> 
  3812                              <1> ; 24/12/2021
  3813                              <1> ; ('swap_in' procedure call is disabled)
  3814                              <1> 
  3815                              <1> ;swap_in:
  3816                              <1> 	; 31/08/2015
  3817                              <1> 	; 20/07/2015
  3818                              <1> 	; 28/04/2015
  3819                              <1> 	; 18/04/2015
  3820                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3821                              <1> 	;
  3822                              <1> 	; INPUT -> 
  3823                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3824                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3825                              <1> 	;	EAX = Offset Address for the swapped page on the
  3826                              <1> 	;	      swap disk or in the swap file.
  3827                              <1> 	;
  3828                              <1> 	; OUTPUT ->
  3829                              <1> 	;	EAX = 0 if loading at memory has been successful
  3830                              <1> 	;
  3831                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3832                              <1> 	;		  or sector not present or drive not ready
  3833                              <1> 	;	     EAX = Error code
  3834                              <1> 	;	     [u.error] = EAX 
  3835                              <1> 	;		       = The last error code for the process
  3836                              <1> 	;		         (will be reset after returning to user)	  
  3837                              <1> 	;
  3838                              <1> 	; Modified Registers -> EAX
  3839                              <1> 	;
  3840                              <1> 
  3841                              <1> ;       cmp     dword [swp_drv], 0
  3842                              <1> ;	jna	short swpin_dnp_err
  3843                              <1> ;
  3844                              <1> ;	cmp	eax, [swpd_size]
  3845                              <1> ;	jnb	short swpin_snp_err
  3846                              <1> ;
  3847                              <1> ;	push	esi
  3848                              <1> ;	push	ebx
  3849                              <1> ;	push	ecx
  3850                              <1> ;	mov	esi, [swp_drv]	
  3851                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3852                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3853                              <1> ;		; size different than 512 bytes, logical disk sector
  3854                              <1> ;		; size is 512 bytes and disk reading procedure
  3855                              <1> ;		; will be performed for reading 4096 bytes
  3856                              <1> ;		; (2*2048, 8*512). 
  3857                              <1> ;	; ESI = Logical disk description table address
  3858                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3859                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3860                              <1> ;	; ECX = Sector count ; 8 sectors
  3861                              <1> ;	push	eax
  3862                              <1> ;	call	logical_disk_read
  3863                              <1> ;	pop	eax
  3864                              <1> ;	jnc	short swpin_read_ok
  3865                              <1> ;	;
  3866                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3867                              <1> ;	mov	[u.error], eax
  3868                              <1> ;	jmp	short swpin_retn
  3869                              <1> ;	;
  3870                              <1> ;swpin_read_ok:
  3871                              <1> ;	; EAX = Offset address (logical sector number)
  3872                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3873                              <1> ;	;
  3874                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3875                              <1> ;	; 20/07/2015
  3876                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3877                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3878                              <1> ;	mov	bl, [u.uno] ; current process number
  3879                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3880                              <1> ;	call	swap_queue_shift
  3881                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3882                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3883                              <1> ;	; zf = 1
  3884                              <1> ;swpin_retn:
  3885                              <1> ;	pop	ecx
  3886                              <1> ;	pop	ebx
  3887                              <1> ;	pop	esi
  3888                              <1> ;	retn
  3889                              <1> ;
  3890                              <1> ;swpin_dnp_err:
  3891                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3892                              <1> ;swpin_err_retn:
  3893                              <1> ;	mov	[u.error], eax
  3894                              <1> ;	stc
  3895                              <1> ;	retn
  3896                              <1> ;
  3897                              <1> ;swpin_snp_err:
  3898                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3899                              <1> ;	jmp	short swpin_err_retn
  3900                              <1> 
  3901                              <1> ; 24/12/2021
  3902                              <1> ; ('swap_out' procedure call is disabled)
  3903                              <1> 
  3904                              <1> ;swap_out:
  3905                              <1> 	; 10/06/2016
  3906                              <1> 	; 07/06/2016
  3907                              <1>         ; 23/05/2016
  3908                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3909                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3910                              <1> 	;
  3911                              <1> 	; INPUT -> 
  3912                              <1> 	;	none
  3913                              <1> 	;
  3914                              <1> 	; OUTPUT ->
  3915                              <1> 	;	EAX = Physical page address (which is swapped out
  3916                              <1> 	;	      for allocating a new page)
  3917                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3918                              <1> 	;		  or sector not present or drive not ready
  3919                              <1> 	;	     EAX = Error code
  3920                              <1> 	;	     [u.error] = EAX 
  3921                              <1> 	;		       = The last error code for the process
  3922                              <1> 	;		         (will be reset after returning to user)	  
  3923                              <1> 	;
  3924                              <1> 	; Modified Registers -> none (except EAX)
  3925                              <1> 	;
  3926                              <1> 
  3927                              <1> ;	cmp 	word [swpq_count], 1
  3928                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3929                              <1> ;
  3930                              <1> ;       ;cmp    dword [swp_drv], 1
  3931                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3932                              <1> ;
  3933                              <1> ;       cmp     dword [swpd_free], 1
  3934                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3935                              <1> ;
  3936                              <1> ;	push	ebx ; *
  3937                              <1> ;swpout_1:
  3938                              <1> ;	; 10/06/2016
  3939                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3940                              <1> ;	call	swap_queue_shift
  3941                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3942                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3943                              <1> ;				       ; pointer in the swap queue
  3944                              <1> ;	; EAX = PTE value of the page
  3945                              <1> ;	; EBX = PTE address of the page
  3946                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3947                              <1> ;	;
  3948                              <1> ;	; 07/06/2016
  3949                              <1> ;	; 19/05/2016
  3950                              <1> ;	; check this page is in timer events or not
  3951                              <1> ;	
  3952                              <1> ;swpout_timer_page_0:
  3953                              <1> ;	push	edx ; **
  3954                              <1> ;
  3955                              <1> ;	; 07/06/2016
  3956                              <1> ;	cmp	byte [timer_events], 0 
  3957                              <1> ;	jna	short swpout_2
  3958                              <1> ;	;
  3959                              <1> ;	mov	dl, [timer_events]
  3960                              <1> ;
  3961                              <1> ;	push	ecx ; ***
  3962                              <1> ;	push	ebx ; ****
  3963                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  3964                              <1> ;			       ; structures 
  3965                              <1> ;swpout_timer_page_1:
  3966                              <1> ;	mov	cl, [ebx]
  3967                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  3968                              <1> ;	jz	short swpout_timer_page_3
  3969                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  3970                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  3971                              <1> ;				; of the response byte address, to
  3972                              <1> ;				; get beginning of the page address)
  3973                              <1> ;	cmp	eax, ecx
  3974                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  3975                              <1> ;	
  3976                              <1> ;	; !same page!
  3977                              <1> ;	;
  3978                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  3979                              <1> ;	; This page will be used by the kernel to put timer event
  3980                              <1> ;	; response (signal return) byte at the requested address;
  3981                              <1> ;	; in order to prevent a possible wrong write (while
  3982                              <1> ;	; this page is swapped out) on physical memory,
  3983                              <1> ;	; we must protect this page against to be swapped out!
  3984                              <1> ;	;
  3985                              <1> ;	pop	ebx ; ****
  3986                              <1> ;	pop	ecx ; ***
  3987                              <1> ;	pop	edx ; **
  3988                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  3989                              <1> ; 
  3990                              <1> ;swpout_timer_page_2:
  3991                              <1> ;	; 07/06/2016
  3992                              <1> ;	dec	dl
  3993                              <1> ;	jz	short swpout_timer_page_4
  3994                              <1> ;swpout_timer_page_3:
  3995                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  3996                              <1> ;	;jnb	short swpout_timer_page_4
  3997                              <1> ;	add	ebx, 16
  3998                              <1> ;	jmp	short swpout_timer_page_1	
  3999                              <1> ;
  4000                              <1> ;swpout_timer_page_4:
  4001                              <1> ;	pop	ebx ; ****
  4002                              <1> ;	pop	ecx ; ***
  4003                              <1> ;swpout_2:
  4004                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4005                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4006                              <1> ;	;
  4007                              <1> ;	call	link_swap_block
  4008                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4009                              <1> ;				       ; because [swpd_free] value
  4010                              <1> ;				       ; was checked at the beginging. 	
  4011                              <1> ;	pop	edx ; **
  4012                              <1> ;	pop	ebx ; *
  4013                              <1> ;	jmp	short swpout_nfspc_err 
  4014                              <1> ;swpout_3:
  4015                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4016                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4017                              <1> ;	;	
  4018                              <1> ;	push	esi ; **
  4019                              <1> ;	push	ecx ; ***
  4020                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4021                              <1> ;	mov	esi, [swp_drv]	
  4022                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4023                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4024                              <1> ;		; size different than 512 bytes, logical disk sector
  4025                              <1> ;		; size is 512 bytes and disk writing procedure
  4026                              <1> ;		; will be performed for writing 4096 bytes
  4027                              <1> ;		; (2*2048, 8*512). 
  4028                              <1> ;	; ESI = Logical disk description table address
  4029                              <1> ;	; EBX = Buffer (Page) address
  4030                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4031                              <1> ;	; ECX = Sector count ; 8 sectors
  4032                              <1> ;	; edx = PTE address
  4033                              <1> ;	call	logical_disk_write
  4034                              <1> ;	; edx = PTE address
  4035                              <1> ;	pop	ecx ; sector address	
  4036                              <1> ;	jnc	short swpout_write_ok
  4037                              <1> ;	;
  4038                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4039                              <1> ;swpout_dw_err:
  4040                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4041                              <1> ;	mov	[u.error], eax
  4042                              <1> ;	jmp	short swpout_retn
  4043                              <1> ;	;
  4044                              <1> ;swpout_write_ok:
  4045                              <1> ;	; EBX = Buffer (page) address
  4046                              <1> ;	; EDX = Page Table Entry address
  4047                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4048                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4049                              <1> ;	mov 	[edx], ecx 
  4050                              <1> ;		; bit 0 = 0 (swapped page)
  4051                              <1> ;	mov	eax, ebx
  4052                              <1> ;swpout_retn:
  4053                              <1> ;	pop	ecx ; ***
  4054                              <1> ;	pop	esi ; **
  4055                              <1> ;	pop	ebx ; *
  4056                              <1> ;	retn
  4057                              <1> ;
  4058                              <1> ;;swpout_dnp_err:
  4059                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4060                              <1> ;;	jmp	short swpout_err_retn
  4061                              <1> ;swpout_nfspc_err:
  4062                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4063                              <1> ;swpout_err_retn:
  4064                              <1> ;	mov	[u.error], eax
  4065                              <1> ;	;stc
  4066                              <1> ;	retn
  4067                              <1> ;swpout_npts_err:
  4068                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4069                              <1> ;	pop	ebx
  4070                              <1> ;	jmp	short swpout_err_retn
  4071                              <1> ;swpout_im_err:
  4072                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4073                              <1> ;	jmp	short swpout_err_retn
  4074                              <1> 
  4075                              <1> ; 24/12/2021
  4076                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4077                              <1> 
  4078                              <1> ;swap_queue_shift:
  4079                              <1> 	; 26/03/2017
  4080                              <1> 	; 10/06/2016
  4081                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4082                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4083                              <1> 	;
  4084                              <1> 	; INPUT ->
  4085                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4086                              <1> 	;	      and process number combination (bit 0 to 11)
  4087                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4088                              <1> 	;	
  4089                              <1> 	; OUTPUT ->
  4090                              <1> 	;	If EBX input > 0 
  4091                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4092                              <1> 	; 	   from the tail to the head, up to entry offset
  4093                              <1> 	; 	   which points to EBX input value or nothing
  4094                              <1> 	;	   to do if EBX value is not found on the queue.
  4095                              <1> 	;	   (The entry -with EBX value- will be removed
  4096                              <1> 	;	   from the queue if it is found.)
  4097                              <1> 	;
  4098                              <1> 	;	   EAX = 0		
  4099                              <1> 	;
  4100                              <1> 	;	If EBX input = 0
  4101                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4102                              <1> 	; 	   from the tail to the head, if the PTE address
  4103                              <1> 	;	   which is pointed in head of the queue is marked
  4104                              <1> 	;	   as "accessed" or it is marked as "non present".
  4105                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4106                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4107                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4108                              <1> 	;	   -without dropping pointer of the PTE from 
  4109                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4110                              <1> 	;	   Pointer in the head will be moved into the tail,
  4111                              <1> 	;	   other PTEs will be shifted on head direction.)
  4112                              <1> 	;
  4113                              <1> 	;	   Swap queue will be shifted up to the first
  4114                              <1> 	;	   'present' or 'non accessed' page will be found
  4115                              <1> 	;	   (as pointed) on the queue head (then it will be
  4116                              <1>         ;          removed/dropped from the queue).
  4117                              <1> 	;
  4118                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4119                              <1> 	;		 (it's pointer -virtual address-) dropped
  4120                              <1> 	;		 (removed) from swap queue.
  4121                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4122                              <1> 	;	         which is (it's pointer -virtual address-)
  4123                              <1> 	;		 dropped (removed) from swap queue.
  4124                              <1> 	;
  4125                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4126                              <1> 	;
  4127                              <1> 	; Modified Registers -> EAX, EBX
  4128                              <1> 	;
  4129                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4130                              <1> ;	and	ax, ax
  4131                              <1> ;	jz	short swpqs_retn
  4132                              <1> ;	push	edi
  4133                              <1> ;	push	esi
  4134                              <1> ;	push	ecx
  4135                              <1> ;	mov	esi, swap_queue
  4136                              <1> ;	mov	ecx, eax
  4137                              <1> ;	or	ebx, ebx
  4138                              <1> ;	jz	short swpqs_7
  4139                              <1> ;swpqs_1:
  4140                              <1> ;	lodsd
  4141                              <1> ;	cmp	eax, ebx
  4142                              <1> ;	je	short swpqs_2
  4143                              <1> ;	loop	swpqs_1
  4144                              <1> ;	; 10/06/2016
  4145                              <1> ;	sub	eax, eax 
  4146                              <1> ;	jmp	short swpqs_6
  4147                              <1> ;swpqs_2:
  4148                              <1> ;	mov	edi, esi
  4149                              <1> ;	sub 	edi, 4
  4150                              <1> ;swpqs_3:
  4151                              <1> ;	dec	word [swpq_count]
  4152                              <1> ;	jz	short swpqs_5
  4153                              <1> ;swpqs_4:
  4154                              <1> ;	dec 	ecx
  4155                              <1> ;	rep	movsd	; shift up (to the head)
  4156                              <1> ;swpqs_5:
  4157                              <1> ;	xor	eax, eax
  4158                              <1> ;	mov	[edi], eax
  4159                              <1> ;swpqs_6:
  4160                              <1> ;	pop	ecx
  4161                              <1> ;	pop	esi
  4162                              <1> ;	pop	edi
  4163                              <1> ;swpqs_retn:
  4164                              <1> ;	retn		
  4165                              <1> ;swpqs_7:
  4166                              <1> ;	mov	edi, esi ; head
  4167                              <1> ;	lodsd
  4168                              <1> ;	; 20/07/2015
  4169                              <1> ;	mov	ebx, eax
  4170                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4171                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4172                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4173                              <1> ;		      ; ax = process number (1 to 4095)
  4174                              <1> ;	cmp	al, [u.uno]
  4175                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4176                              <1> ;	jne	short swpqs_8
  4177                              <1> ;	mov	eax, [u.pgdir]
  4178                              <1> ;	jmp	short swpqs_9
  4179                              <1> ;swpqs_8:
  4180                              <1> ;	; 09/06/2016
  4181                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4182                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4183                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4184                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4185                              <1> ;
  4186                              <1> ;	;shl	ax, 2
  4187                              <1> ;	shl	al, 2
  4188                              <1> ;	mov 	eax, [eax+p.upage-4]
  4189                              <1> ;	or	eax, eax
  4190                              <1> ;	jz	short swpqs_3 ; invalid upage
  4191                              <1> ;	add	eax, u.pgdir - user
  4192                              <1> ;			 ; u.pgdir value for the process
  4193                              <1> ;			 ; is in [eax]
  4194                              <1> ;	mov	eax, [eax]
  4195                              <1> ;	and	eax, eax
  4196                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4197                              <1> ;swpqs_9:
  4198                              <1> ;	push	edx
  4199                              <1> ;	; eax = page directory
  4200                              <1> ;	; ebx = virtual address
  4201                              <1> ;	call	get_pte
  4202                              <1> ;	mov	ebx, edx	; PTE address
  4203                              <1> ;	pop	edx
  4204                              <1> ;	; 10/06/2016
  4205                              <1> ;	jc	short swpqs_13 ; empty PDE
  4206                              <1> ;	; EAX = PTE value
  4207                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4208                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4209                              <1> ;			        ; from the queue (head)
  4210                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4211                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4212                              <1> ;			        ; from the queue (head) 	
  4213                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4214                              <1> ;	;jnz	short swpqs_11  ; present
  4215                              <1> ;			        ; accessed page
  4216                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4217                              <1> ;	jc	short swpqs_11  ; accessed page
  4218                              <1> ;
  4219                              <1> ;	dec	ecx
  4220                              <1> ;	mov	[swpq_count], cx
  4221                              <1> ;       jz      short swpqs_10
  4222                              <1> ;		; esi = head + 4
  4223                              <1> ;		; edi = head
  4224                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4225                              <1> ;swpqs_10:
  4226                              <1> ;	mov	[edi], ecx ; 0
  4227                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4228                              <1> ;
  4229                              <1> ;swpqs_11:
  4230                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4231                              <1> ;	; Rotation (head -> tail)
  4232                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4233                              <1> ;	jz	short swpqs_10
  4234                              <1> ;		; esi = head + 4
  4235                              <1> ;		; edi = head
  4236                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4237                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4238                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4239                              <1> ;
  4240                              <1> ;	mov	cx, [swpq_count]
  4241                              <1> ;
  4242                              <1> ;swpqs_12:
  4243                              <1> ;	mov	esi, swap_queue ; head
  4244                              <1> ;       jmp     swpqs_7
  4245                              <1> ;
  4246                              <1> ;swpqs_13:
  4247                              <1> ;	dec	ecx
  4248                              <1> ;	mov	[swpq_count], cx
  4249                              <1> ;       jz      swpqs_5
  4250                              <1> ;	jmp	short swpqs_12
  4251                              <1> 
  4252                              <1> ; 24/12/2021
  4253                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4254                              <1> 
  4255                              <1> ;add_to_swap_queue:
  4256                              <1> 	; 20/02/2017
  4257                              <1> 	; 20/07/2015
  4258                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4259                              <1> 	;
  4260                              <1> 	; Adds new page to swap queue
  4261                              <1> 	; (page directories and page tables must not be added
  4262                              <1> 	; to swap queue)	
  4263                              <1> 	;
  4264                              <1> 	; INPUT ->
  4265                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4266                              <1> 	;	[u.uno]
  4267                              <1> 	;	20/02/2017
  4268                              <1> 	;	(Linear address = CORE + user's virtual address)
  4269                              <1> 	;
  4270                              <1> 	; OUTPUT ->
  4271                              <1> 	;	EAX = [swpq_count]
  4272                              <1> 	;	      (after the PTE has been added)
  4273                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4274                              <1> 	;	      the PTE could not be added.
  4275                              <1> 	;
  4276                              <1> 	; Modified Registers -> EAX
  4277                              <1> 	;
  4278                              <1> ;	push	ebx
  4279                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4280                              <1> ;	mov	bl, [u.uno] ; current process number
  4281                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4282                              <1> ;				 ; it is already on the queue
  4283                              <1> ;		; then add it to the tail of the queue
  4284                              <1> ;	movzx	eax, word [swpq_count]
  4285                              <1> ;	cmp	ax, 1024
  4286                              <1> ;	jb	short atsq_1
  4287                              <1> ;	sub	ax, ax
  4288                              <1> ;	pop	ebx
  4289                              <1> ;	retn
  4290                              <1> ;atsq_1:
  4291                              <1> ;	push	esi
  4292                              <1> ;	mov	esi, swap_queue
  4293                              <1> ;	and	ax, ax
  4294                              <1> ;	jz	short atsq_2
  4295                              <1> ;	shl	ax, 2	; convert to offset
  4296                              <1> ;	add	esi, eax
  4297                              <1> ;	shr	ax, 2
  4298                              <1> ;atsq_2:
  4299                              <1> ;	inc	ax
  4300                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4301                              <1> ;	mov	[swpq_count], ax
  4302                              <1> ;	pop	esi
  4303                              <1> ;	pop	ebx
  4304                              <1> ;	retn
  4305                              <1> 
  4306                              <1> ; 24/12/2021
  4307                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4308                              <1> 
  4309                              <1> ;unlink_swap_block:
  4310                              <1> 	; 15/09/2015
  4311                              <1> 	; 30/04/2015
  4312                              <1> 	; 18/04/2015
  4313                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4314                              <1> 	;
  4315                              <1> 	; INPUT -> 
  4316                              <1> 	;	EAX = swap disk/file offset address
  4317                              <1> 	;	      (bit 1 to bit 31)
  4318                              <1> 	; OUTPUT ->
  4319                              <1> 	;	[swpd_free] is increased
  4320                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4321                              <1> 	;
  4322                              <1> 	; Modified Registers -> EAX
  4323                              <1> 	;
  4324                              <1> ;	push	ebx
  4325                              <1> ;	push	edx
  4326                              <1> ;	;
  4327                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4328                              <1> ;				     ; 3 bits right
  4329                              <1> ;				     ; to get swap block/page number
  4330                              <1> ;	mov	edx, eax
  4331                              <1> ;	; 15/09/2015
  4332                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4333                              <1> ;				     ; (1 allocation bit = 1 page)
  4334                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4335                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4336                              <1> ;				     ; (to get 32 bit position)			
  4337                              <1> ;	;
  4338                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4339                              <1> ;	add	ebx, edx
  4340                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4341                              <1> ;				     ; (allocation bit position)	 
  4342                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4343                              <1> ;				     ; than the address in 'swpd_next' ?
  4344                              <1> ;				     ; (next/first free block value)		
  4345                              <1> ;	jnb	short uswpbl_1	     ; no	
  4346                              <1> ;	mov	[swpd_next], eax     ; yes	
  4347                              <1> ;uswpbl_1:
  4348                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4349                              <1> ;				     ; set relevant bit to 1.
  4350                              <1> ;				     ; set CF to the previous bit value	
  4351                              <1> ;	cmc			     ; complement carry flag	
  4352                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4353                              <1> ;				     ; if the block is already deallocated
  4354                              <1> ;				     ; before.	
  4355                              <1> ;       inc     dword [swpd_free]
  4356                              <1> ;uswpbl_2:
  4357                              <1> ;	pop	edx
  4358                              <1> ;	pop	ebx
  4359                              <1> ;	retn
  4360                              <1> 
  4361                              <1> ; 24/12/2021
  4362                              <1> ; ('link_swap_block' procedure call is disabled)
  4363                              <1> 
  4364                              <1> ;link_swap_block:
  4365                              <1> 	; 01/07/2015
  4366                              <1> 	; 18/04/2015
  4367                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4368                              <1> 	;
  4369                              <1> 	; INPUT -> none
  4370                              <1> 	;
  4371                              <1> 	; OUTPUT ->
  4372                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4373                              <1> 	;	      in sectors (corresponding 
  4374                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4375                              <1> 	;
  4376                              <1> 	;	CF = 1 and EAX = 0 
  4377                              <1> 	; 		   if there is not a free block to be allocated	
  4378                              <1> 	;
  4379                              <1> 	; Modified Registers -> none (except EAX)
  4380                              <1> 	;
  4381                              <1> 
  4382                              <1> ;	;mov	eax, [swpd_free]
  4383                              <1> ;	;and	eax, eax
  4384                              <1> ;	;jz	short out_of_swpspc
  4385                              <1> ;	;
  4386                              <1> ;	push	ebx
  4387                              <1> ;	push	ecx
  4388                              <1> ;	;
  4389                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4390                              <1> ;	mov	ecx, ebx
  4391                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4392                              <1> ;				 ; next_free_swap_block >> 5
  4393                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4394                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4395                              <1> ;lswbl_scan:
  4396                              <1> ;	cmp	ebx, ecx
  4397                              <1> ;	ja	short lswbl_notfound
  4398                              <1> ;	;
  4399                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4400                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4401                              <1> ;			   ; loads the destination with an index to
  4402                              <1> ;			   ; first set bit. (0 -> 31) 
  4403                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4404                              <1> ;	; 01/07/2015
  4405                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4406                              <1> ;			 ;
  4407                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4408                              <1> ;			 ;	  with value of 1 means 
  4409                              <1> ;			 ;	  the corresponding page is free 
  4410                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4411                              <1> ;	add	ebx, 4
  4412                              <1> ;			 ; We return back for searching next page block
  4413                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4414                              <1> ;			 ;	 we always will find at least 1 free block here.
  4415                              <1> ;	jmp    	short lswbl_scan
  4416                              <1> ;	;
  4417                              <1> ;lswbl_notfound:	
  4418                              <1> ;	sub	ecx, swap_alloc_table
  4419                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4420                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4421                              <1> ;	xor	eax, eax
  4422                              <1> ;	mov	[swpd_free], eax
  4423                              <1> ;	stc
  4424                              <1> ;lswbl_ok:
  4425                              <1> ;	pop	ecx
  4426                              <1> ;	pop	ebx
  4427                              <1> ;	retn
  4428                              <1> ;	;
  4429                              <1> ;;out_of_swpspc:
  4430                              <1> ;;	stc
  4431                              <1> ;;	retn
  4432                              <1> ;
  4433                              <1> ;lswbl_found:
  4434                              <1> ;	mov	ecx, ebx
  4435                              <1> ;	sub	ecx, swap_alloc_table
  4436                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4437                              <1> ;				 ; address/offset (to the next)
  4438                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4439                              <1> ;	;
  4440                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4441                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4442                              <1> ;				 ; in the destination.
  4443                              <1> ;				 ;
  4444                              <1> ;				 ; Reset the bit which is corresponding to the 
  4445                              <1> ;				 ; (just) allocated block.
  4446                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4447                              <1> ;	add	eax, ecx	 ; = block number
  4448                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4449                              <1> ;				 ; 1 block =  8 sectors
  4450                              <1> ;	;
  4451                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4452                              <1> ;	;
  4453                              <1> ;	; NOTE: The relevant page table entry will be updated
  4454                              <1> ;	;       according to this EAX value...
  4455                              <1> ;	;
  4456                              <1> ;	jmp	short lswbl_ok
  4457                              <1> 
  4458                              <1> ; 24/12/2021
  4459                              <1> ; ('logical_disk_read' procedure call is disabled)
  4460                              <1> 
  4461                              <1> ;logical_disk_read:
  4462                              <1> 	; 20/07/2015
  4463                              <1> 	; 09/03/2015 (temporary code here)
  4464                              <1> 	;
  4465                              <1> 	; INPUT ->
  4466                              <1> 	; 	ESI = Logical disk description table address
  4467                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4468                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4469                              <1> 	; 	ECX = Sector count
  4470                              <1> 	;
  4471                              <1> 	;
  4472                              <1> ;	retn
  4473                              <1> 
  4474                              <1> ; 24/12/2021
  4475                              <1> ; ('logical_disk_write' procedure call is disabled)
  4476                              <1> 
  4477                              <1> ;logical_disk_write:
  4478                              <1> 	; 20/07/2015
  4479                              <1> 	; 09/03/2015 (temporary code here)
  4480                              <1> 	;
  4481                              <1> 	; INPUT ->
  4482                              <1> 	; 	ESI = Logical disk description table address
  4483                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4484                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4485                              <1> 	; 	ECX = Sector count
  4486                              <1> 	;
  4487                              <1> ;	retn
  4488                              <1> 
  4489                              <1> get_physical_addr:
  4490                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4491                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4492                              <1> 	; 18/10/2015
  4493                              <1> 	; 29/07/2015
  4494                              <1> 	; 20/07/2015
  4495                              <1> 	; 04/06/2015
  4496                              <1> 	; 20/05/2015
  4497                              <1> 	; 28/04/2015
  4498                              <1> 	; 18/04/2015
  4499                              <1> 	; Get physical address
  4500                              <1> 	;     (allocates a new page for user if it is not present)
  4501                              <1> 	;	
  4502                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4503                              <1> 	; (buffer) address to physical address (of the buffer).)
  4504                              <1> 	; ('sys write', 'sys read' system calls...)
  4505                              <1> 	;
  4506                              <1> 	; INPUT ->
  4507                              <1> 	;	EBX = virtual address
  4508                              <1> 	;	u.pgdir = page directory (physical) address
  4509                              <1> 	;
  4510                              <1> 	; OUTPUT ->
  4511                              <1> 	;	EAX = physical address 
  4512                              <1> 	;	EBX = linear address	
  4513                              <1> 	;	EDX = physical address of the page frame
  4514                              <1> 	;	      (with attribute bits)
  4515                              <1> 	;	ECX = byte count within the page frame
  4516                              <1> 	;
  4517                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4518                              <1> 	;
  4519                              <1> 
  4520                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4521 000031B8 A1[AF700000]        <1> 	mov	eax, [u.pgdir]
  4522                              <1> 
  4523                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4524                              <1> 	
  4525 000031BD 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4526                              <1> 	;
  4527                              <1> 	;mov	eax, [u.pgdir]
  4528 000031C3 E816FDFFFF          <1> 	call	get_pte
  4529                              <1> 		; EDX = Page table entry address (if CF=0)
  4530                              <1> 	        ;       Page directory entry address (if CF=1)
  4531                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4532                              <1> 		; EAX = Page table entry value (page address)
  4533                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4534 000031C8 731C                <1> 	jnc	short gpa_1
  4535                              <1> 	;
  4536 000031CA E8FDFBFFFF          <1> 	call	allocate_page
  4537 000031CF 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4538                              <1> gpa_0:
  4539 000031D1 E867FCFFFF          <1> 	call 	clear_page
  4540                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4541 000031D6 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4542                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4543                              <1> 			   ; (user, writable, present page)	
  4544 000031D8 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4545 000031DA A1[AF700000]        <1> 	mov	eax, [u.pgdir]	
  4546 000031DF E8FAFCFFFF          <1> 	call	get_pte
  4547 000031E4 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4548                              <1> gpa_1:
  4549                              <1> 	; EAX = PTE value, EDX = PTE address
  4550 000031E6 A801                <1> 	test 	al, PTE_A_PRESENT
  4551 000031E8 750A                <1> 	jnz	short gpa_3
  4552 000031EA 09C0                <1> 	or	eax, eax
  4553 000031EC 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4554                              <1> 
  4555                              <1> ; 24/12/2021
  4556                              <1> ; ('reload_page' procedure call is disabled)
  4557 000031EE EB2C                <1> 	jmp	short gpa_im_err
  4558                              <1> 
  4559                              <1> 	; 20/07/2015
  4560                              <1> ;	push	ebp
  4561                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4562                              <1> ;	; reload swapped page
  4563                              <1> ;	call	reload_page ; 28/04/2015
  4564                              <1> ;	pop	ebp
  4565                              <1> ;	jc	short gpa_retn
  4566                              <1> gpa_2:
  4567                              <1> ; 24/12/2021
  4568                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4569                              <1> 
  4570                              <1> 	; 20/07/2015
  4571                              <1> 	; 20/05/2015
  4572                              <1> 	; add this page to swap queue
  4573                              <1> ;	push	eax 
  4574                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4575                              <1> ;	call 	add_to_swap_queue
  4576                              <1> ;	pop	eax
  4577                              <1> 		; PTE address in EDX
  4578                              <1> 		; virtual address in EBX
  4579                              <1> 	; EAX = memory page address
  4580 000031F0 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4581                              <1> 				  ; present flag, bit 0 = 1
  4582                              <1> 				  ; user flag, bit 2 = 1	
  4583                              <1> 				  ; writable flag, bit 1 = 1
  4584 000031F2 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4585                              <1> gpa_3:
  4586                              <1> 	; 18/10/2015
  4587 000031F4 89D9                <1> 	mov	ecx, ebx
  4588 000031F6 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4589 000031FC 89C2                <1> 	mov 	edx, eax
  4590 000031FE 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4591 00003202 01C8                <1> 	add	eax, ecx
  4592 00003204 F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4593 00003206 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4594 0000320C F8                  <1> 	clc
  4595                              <1> gpa_retn:
  4596 0000320D C3                  <1> 	retn	
  4597                              <1> gpa_4:	
  4598 0000320E E8B9FBFFFF          <1> 	call	allocate_page
  4599 00003213 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4600 00003215 E823FCFFFF          <1> 	call	clear_page
  4601 0000321A EBD4                <1> 	jmp	short gpa_2
  4602                              <1> 
  4603                              <1> gpa_im_err:	
  4604 0000321C B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4605                              <1> 				  ; Major error = 0 (No protection fault)	
  4606 00003221 C3                  <1> 	retn
  4607                              <1> 
  4608                              <1> ; 24/12/2021
  4609                              <1> ; ('reload_page' procedure call is disabled)
  4610                              <1> 
  4611                              <1> ;reload_page:
  4612                              <1> 	; 20/07/2015
  4613                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4614                              <1> 	;
  4615                              <1> 	; Reload (Restore) swapped page at memory
  4616                              <1> 	;
  4617                              <1> 	; INPUT -> 
  4618                              <1> 	;	EBP = Virtual (linear) memory address
  4619                              <1> 	;	EAX = PTE value (swap disk sector address)
  4620                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4621                              <1> 	; OUTPUT ->
  4622                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4623                              <1> 	;
  4624                              <1> 	;	CF = 1 and EAX = error code
  4625                              <1> 	;
  4626                              <1> 	; Modified Registers -> none (except EAX)
  4627                              <1> 	;
  4628                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4629                              <1> ;	push	ebx      ;
  4630                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4631                              <1> ;	call	allocate_page
  4632                              <1> ;	jc	short rlp_im_err
  4633                              <1> ;	xchg 	eax, ebx	
  4634                              <1> ;	; EBX = Physical memory (page) address
  4635                              <1> ;	; EAX = Swap disk (offset) address
  4636                              <1> ;	; EBP = Virtual (linear) memory address
  4637                              <1> ;	call	swap_in
  4638                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4639                              <1> ;	mov	eax, ebx	
  4640                              <1> ;rlp_retn:
  4641                              <1> ;	pop	ebx
  4642                              <1> ;	retn
  4643                              <1> ;	
  4644                              <1> ;rlp_im_err:	
  4645                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4646                              <1> ;				  ; Major error = 0 (No protection fault)	
  4647                              <1> ;	jmp	short rlp_retn
  4648                              <1> ;
  4649                              <1> ;rlp_swp_err:
  4650                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4651                              <1> ;	jmp	short rlp_retn
  4652                              <1> 
  4653                              <1> copy_page_dir:
  4654                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4655                              <1> 	; 19/09/2015
  4656                              <1> 	; temporary - 07/09/2015
  4657                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4658                              <1> 	;
  4659                              <1> 	; INPUT -> 
  4660                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4661                              <1> 	;		    page directory.
  4662                              <1> 	; OUTPUT ->
  4663                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4664                              <1> 	;	       page directory.
  4665                              <1> 	;	(New page directory with new page table entries.)
  4666                              <1> 	;	(New page tables with read only copies of the parent's
  4667                              <1> 	;	pages.)
  4668                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4669                              <1> 	;
  4670                              <1> 	; Modified Registers -> none (except EAX)
  4671                              <1> 	;
  4672 00003222 E8A5FBFFFF          <1> 	call	allocate_page
  4673 00003227 723E                <1> 	jc	short cpd_err
  4674                              <1> 	;
  4675 00003229 55                  <1> 	push	ebp ; 20/07/2015
  4676 0000322A 56                  <1> 	push	esi
  4677 0000322B 57                  <1> 	push	edi
  4678 0000322C 53                  <1> 	push	ebx
  4679 0000322D 51                  <1> 	push	ecx
  4680 0000322E 8B35[AF700000]      <1> 	mov	esi, [u.pgdir]
  4681 00003234 89C7                <1> 	mov	edi, eax
  4682 00003236 50                  <1> 	push	eax ; save child's page directory address
  4683                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4684                              <1> 	; (use same system space for all user page tables) 
  4685 00003237 A5                  <1> 	movsd
  4686 00003238 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4687 0000323D B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4688                              <1> cpd_0:	
  4689 00003242 AD                  <1> 	lodsd
  4690                              <1> 	;or	eax, eax
  4691                              <1>         ;jnz	short cpd_1
  4692 00003243 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4693 00003245 7508                <1> 	jnz	short cpd_1
  4694                              <1>  	; (virtual address at the end of the page table)	
  4695 00003247 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4696 0000324D EB0F                <1> 	jmp	short cpd_2
  4697                              <1> cpd_1:	
  4698 0000324F 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4699 00003253 89C3                <1> 	mov	ebx, eax
  4700                              <1> 	; EBX = Parent's page table address
  4701 00003255 E81F000000          <1> 	call	copy_page_table
  4702 0000325A 720C                <1> 	jc	short cpd_p_err
  4703                              <1> 	; EAX = Child's page table address
  4704 0000325C 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4705                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4706                              <1> 			 ; (present, writable, user)
  4707                              <1> cpd_2:
  4708 0000325E AB                  <1> 	stosd
  4709 0000325F E2E1                <1> 	loop	cpd_0
  4710                              <1> 	;
  4711 00003261 58                  <1> 	pop	eax  ; restore child's page directory address
  4712                              <1> cpd_3:
  4713 00003262 59                  <1> 	pop	ecx
  4714 00003263 5B                  <1> 	pop	ebx
  4715 00003264 5F                  <1> 	pop	edi
  4716 00003265 5E                  <1> 	pop	esi
  4717 00003266 5D                  <1> 	pop	ebp
  4718                              <1> cpd_err:
  4719 00003267 C3                  <1> 	retn
  4720                              <1> cpd_p_err:
  4721                              <1> 	; release the allocated pages missing (recover free space)
  4722 00003268 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4723 00003269 8B1D[AF700000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4724 0000326F E888FCFFFF          <1> 	call 	deallocate_page_dir
  4725 00003274 29C0                <1> 	sub	eax, eax ; 0
  4726 00003276 F9                  <1> 	stc
  4727 00003277 EBE9                <1> 	jmp	short cpd_3	
  4728                              <1> 
  4729                              <1> copy_page_table:
  4730                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4731                              <1> 	; 19/09/2015
  4732                              <1> 	; temporary - 07/09/2015
  4733                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4734                              <1> 	;
  4735                              <1> 	; INPUT -> 
  4736                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4737                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4738                              <1> 	; OUTPUT ->
  4739                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4740                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4741                              <1> 	;	CF = 1 -> error 
  4742                              <1> 	;
  4743                              <1> 	; Modified Registers -> EBP (except EAX)
  4744                              <1> 	;
  4745 00003279 E84EFBFFFF          <1> 	call	allocate_page
  4746 0000327E 7244                <1> 	jc	short cpt_err
  4747                              <1> 	;
  4748 00003280 50                  <1> 	push	eax ; *
  4749                              <1> 	;push 	ebx
  4750 00003281 56                  <1> 	push	esi
  4751 00003282 57                  <1> 	push	edi
  4752 00003283 52                  <1> 	push	edx
  4753 00003284 51                  <1> 	push	ecx
  4754                              <1> 	;
  4755 00003285 89DE                <1> 	mov	esi, ebx
  4756 00003287 89C7                <1> 	mov	edi, eax
  4757 00003289 89C2                <1> 	mov	edx, eax
  4758 0000328B 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4759                              <1> cpt_0:
  4760 00003291 AD                  <1> 	lodsd
  4761 00003292 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4762                              <1> 	;jnz	short cpt_1 (*)
  4763                              <1> 	; 24/12/2021
  4764                              <1> 	;and	eax, eax (*)
  4765 00003294 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4766                              <1> 	
  4767                              <1> ; 24/12/2021
  4768                              <1> ; ('reload_page' procedure call is disabled)
  4769                              <1> ;
  4770                              <1> ;	; ebp = virtual (linear) address of the memory page
  4771                              <1> ;	call	reload_page ; 28/04/2015
  4772                              <1> ;	jc	short cpt_p_err
  4773                              <1> cpt_1:
  4774 00003296 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4775 0000329A 89C1                <1> 	mov	ecx, eax
  4776                              <1> 	; Allocate a new page for the child process
  4777 0000329C E82BFBFFFF          <1> 	call	allocate_page
  4778 000032A1 721C                <1> 	jc	short cpt_p_err
  4779 000032A3 57                  <1> 	push	edi
  4780 000032A4 56                  <1> 	push	esi
  4781 000032A5 89CE                <1> 	mov	esi, ecx
  4782 000032A7 89C7                <1> 	mov	edi, eax
  4783 000032A9 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4784 000032AE F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4785 000032B0 5E                  <1> 	pop	esi
  4786 000032B1 5F                  <1> 	pop	edi
  4787                              <1> 	; 
  4788                              <1> ; 24/12/2021
  4789                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4790                              <1> ;
  4791                              <1> ;	push	ebx
  4792                              <1> ;	push	eax
  4793                              <1> ;	mov	ebx, ebp
  4794                              <1> ;	; ebx = virtual address of the memory page
  4795                              <1> ;	call	add_to_swap_queue
  4796                              <1> ;	pop	eax
  4797                              <1> ;	pop	ebx
  4798                              <1> 	;
  4799                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4800 000032B2 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4801                              <1> cpt_2:
  4802 000032B4 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4803                              <1> 	;
  4804 000032B5 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4805                              <1> 	;
  4806 000032BB 39D7                <1> 	cmp	edi, edx
  4807 000032BD 72D2                <1> 	jb	short cpt_0
  4808                              <1> cpt_p_err:
  4809 000032BF 59                  <1> 	pop	ecx
  4810 000032C0 5A                  <1> 	pop	edx
  4811 000032C1 5F                  <1> 	pop	edi
  4812 000032C2 5E                  <1> 	pop	esi
  4813                              <1> 	;pop	ebx
  4814 000032C3 58                  <1> 	pop	eax ; *
  4815                              <1> cpt_err:
  4816 000032C4 C3                  <1> 	retn
  4817                              <1> 
  4818                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4819                              <1> 
  4820                              <1> ;; Data:
  4821                              <1> 
  4822                              <1> ; 09/03/2015
  4823                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4824                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4825                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4826                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4827                              <1> ;swpd_next:  dd 0 ; next free page block
  4828                              <1> ;swpd_last:  dd 0 ; last swap page block
  2046                                  %include 'sysdefs.inc' ; 09/03/2015
  2047                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYSDEFS.INC
  2048                              <1> ; Last Modification: 13/06/2022
  2049                              <1> ;
  2050                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2051                              <1> ; (Modified from 
  2052                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2053                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2054                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2055                              <1> ; ----------------------------------------------------------------------------
  2056                              <1> ;
  2057                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2058                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2059                              <1> ; <Bell Laboratories (17/3/1972)>
  2060                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2061                              <1> ;
  2062                              <1> ; ****************************************************************************
  2063                              <1> 
  2064                              <1> nproc 	equ	16  ; number of processes
  2065                              <1> nfiles 	equ	50
  2066                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2067                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2068                              <1> 
  2069                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2070                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2071                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2072                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2073                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2074                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2075                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2076                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2077                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2078                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2079                              <1> 	; '/core' dump file size = 32768 bytes
  2080                              <1>  
  2081                              <1> ; 08/03/2014 
  2082                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2083                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2084                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2085                              <1> 
  2086                              <1> ; 30/08/2013
  2087                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2088                              <1> 
  2089                              <1> ; 05/02/2014
  2090                              <1> ; process status
  2091                              <1> ;SFREE 	equ 0
  2092                              <1> ;SRUN	equ 1
  2093                              <1> ;SWAIT	equ 2
  2094                              <1> ;SZOMB	equ 3
  2095                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2096                              <1> 
  2097                              <1> ; 09/03/2015
  2098                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2099                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2100                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2101                              <1> 
  2102                              <1> ; 17/09/2015
  2103                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2104                              <1> 
  2105                              <1> ; 21/09/2015 (36) 
  2106                              <1> ; 01/07/2015 (35)
  2107                              <1> ; 14/07/2013 (0-34)
  2108                              <1> ; UNIX v1 system calls
  2109                              <1> _rele 	equ 0
  2110                              <1> _exit 	equ 1
  2111                              <1> _fork 	equ 2
  2112                              <1> _read 	equ 3
  2113                              <1> _write	equ 4
  2114                              <1> _open	equ 5
  2115                              <1> _close 	equ 6
  2116                              <1> _wait 	equ 7
  2117                              <1> _creat 	equ 8
  2118                              <1> _link 	equ 9
  2119                              <1> _unlink	equ 10
  2120                              <1> _exec	equ 11
  2121                              <1> _chdir	equ 12
  2122                              <1> _time 	equ 13
  2123                              <1> _mkdir 	equ 14
  2124                              <1> _chmod	equ 15
  2125                              <1> _chown	equ 16
  2126                              <1> _break	equ 17
  2127                              <1> _stat	equ 18
  2128                              <1> _seek	equ 19
  2129                              <1> _tell 	equ 20
  2130                              <1> _mount	equ 21
  2131                              <1> _umount	equ 22
  2132                              <1> _setuid	equ 23
  2133                              <1> _getuid	equ 24
  2134                              <1> _stime	equ 25
  2135                              <1> _quit	equ 26	
  2136                              <1> _intr	equ 27
  2137                              <1> _fstat	equ 28
  2138                              <1> _emt 	equ 29
  2139                              <1> _mdate 	equ 30
  2140                              <1> _stty 	equ 31
  2141                              <1> _gtty	equ 32
  2142                              <1> _ilgins	equ 33
  2143                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2144                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2145                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2146                              <1> 
  2147                              <1> %macro sys 1-4
  2148                              <1>     ; 13/04/2015
  2149                              <1>     ; Retro UNIX 386 v1 system call.		
  2150                              <1>     mov eax, %1
  2151                              <1>     %if %0 >= 2   
  2152                              <1>         mov ebx, %2
  2153                              <1>         %if %0 >= 3    
  2154                              <1>             mov ecx, %3
  2155                              <1>             %if %0 = 4
  2156                              <1>                mov edx, %4   
  2157                              <1>             %endif
  2158                              <1>         %endif
  2159                              <1>     %endif
  2160                              <1>     int 30h	   
  2161                              <1> %endmacro
  2162                              <1> 
  2163                              <1> ; 13/05/2015 - ERROR CODES
  2164                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2165                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2166                              <1> ; 14/05/2015
  2167                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2168                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2169                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2170                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2171                              <1> ; 16/05/2015		
  2172                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2173                              <1> ; 18/05/2015
  2174                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2175                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2176                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2177                              <1> ; 07/06/2015
  2178                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2179                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2180                              <1> ; 09/06/2015
  2181                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2182                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2183                              <1> ; 16/06/2015
  2184                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2185                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2186                              <1> ; 22/06/2015
  2187                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2188                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2189                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2190                              <1> ; 23/06/2015
  2191                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2192                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2193                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2194                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2195                              <1> ; 27/06/2015
  2196                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2197                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2198                              <1> ; 29/06/2015
  2199                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2200                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2201                              <1> ; 12/02/2022 
  2202                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2203                              <1> ; 10/10/2016
  2204                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2205                              <1> ; 18/05/2016
  2206                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2207                              <1> ; 15/10/2016
  2208                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2209                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2210                              <1> ; 16/10/2016
  2211                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2212                              <1> ; 08/02/2022
  2213                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2214                              <1> 
  2215                              <1> ; 13/06/2022
  2216                              <1> ; printer errors
  2217                              <1> ERR_PRN_NOT_RDY	   equ 15 ; 'device not ready !' error
  2218                              <1> ERR_PRN_TIMEOUT	   equ 25 ; 'time out !' error
  2219                              <1> ERR_PRN_PAPER	   equ 31 ; 'out of paper !' error
  2220                              <1> ERR_PRN_IO	   equ 32 ; 'io error !' error
  2221                              <1> ERR_PRN_BUSY	   equ 34 ; 'busy !' error	
  2222                              <1> 
  2223                              <1> ; 26/08/2015
  2224                              <1> ; 24/07/2015
  2225                              <1> ; 24/06/2015
  2226                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2227                              <1> ; 01/07/2015
  2228                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2229                              <1> ;	 					 		
  2047                                  %include 'u0.s'        ; 15/03/2015
  2048                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYS0.INC
  2049                              <1> ; Last Modification: 02/06/2022
  2050                              <1> ; ----------------------------------------------------------------------------
  2051                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2052                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2053                              <1> ;
  2054                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2055                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2056                              <1> ; <Bell Laboratories (17/3/1972)>
  2057                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2058                              <1> ;
  2059                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2060                              <1> ;
  2061                              <1> ; ****************************************************************************
  2062                              <1> ; 21/11/2015
  2063                              <1> 
  2064                              <1> sys_init:
  2065                              <1> 	; 27/02/2022
  2066                              <1> 	; 23/02/2022
  2067                              <1> 	; 04/02/2022
  2068                              <1> 	; 18/10/2015
  2069                              <1> 	; 28/08/2015
  2070                              <1> 	; 24/08/2015
  2071                              <1> 	; 14/08/2015
  2072                              <1> 	; 24/07/2015 
  2073                              <1> 	; 02/07/2015
  2074                              <1> 	; 01/07/2015
  2075                              <1> 	; 23/06/2015
  2076                              <1> 	; 15/04/2015
  2077                              <1> 	; 13/04/2015
  2078                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2079                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2080                              <1> 	;
  2081                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2082                              <1> 	;
  2083                              <1> 	; 14/02/2014
  2084                              <1> 	; 14/07/2013
  2085                              <1> 	;;mov	ax, 41
  2086                              <1> 	; 27/02/2022
  2087                              <1> 	;xor	eax, eax
  2088                              <1> 	;mov	al, 41
  2089                              <1> 	;mov	[rootdir], ax
  2090                              <1> 	;mov	[u.cdir], ax
  2091                              <1> 	;;and	al, 1 ; 15/04/2015
  2092                              <1> 	;inc	al  ; ax = 1
  2093 000032C5 B001                <1> 	mov	al, 1
  2094 000032C7 A2[A5700000]        <1> 	mov	[u.uno], al
  2095                              <1> 	;mov	[mpid], ax
  2096                              <1> 	;mov	[p.pid], ax
  2097 000032CC A2[4A700000]        <1> 	mov	[mpid], al
  2098 000032D1 A2[786D0000]        <1> 	mov	[p.pid], al	
  2099 000032D6 A2[D86D0000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2100                              <1> 	; 27/02/2022
  2101 000032DB B029                <1> 	mov	al, 41
  2102                              <1> 	;mov	[rootdir], ax
  2103                              <1> 	;mov	[u.cdir], ax
  2104 000032DD A2[4C700000]        <1> 	mov	[rootdir], al
  2105 000032E2 A2[60700000]        <1> 	mov	[u.cdir], al
  2106                              <1> 	;
  2107                              <1> 	; 23/02/2022
  2108                              <1>  	;call	epoch
  2109                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2110                              <1> 	; 17/07/2013
  2111 000032E7 E88B060000          <1> 	call 	bf_init ; buffer initialization
  2112                              <1> 	; 23/02/2022
  2113                              <1> 	; (save sysinit time on sb0)
  2114 000032EC E830030000          <1> 	call	epoch
  2115 000032F1 A3[A07E0000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2116                              <1> 	; 23/06/2015
  2117 000032F6 E8D1FAFFFF          <1> 	call	allocate_page
  2118                              <1> 	;;jc	error
  2119                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2120                              <1> 	; 04/02/2022
  2121 000032FB 7305                <1> 	jnc	short sysinit_1
  2122 000032FD E990000000          <1> 	jmp	panic
  2123                              <1> sysinit_1:
  2124 00003302 A3[A6700000]        <1> 	mov	[u.upage], eax ; user structure page	
  2125 00003307 A3[E86D0000]        <1> 	mov	[p.upage], eax
  2126                              <1> 	;
  2127 0000330C E82CFBFFFF          <1> 	call	clear_page
  2128                              <1> 	;
  2129                              <1> 	; 14/08/2015
  2130 00003311 FA                  <1> 	cli
  2131                              <1> 	; 14/03/2015
  2132                              <1> 	; 17/01/2014
  2133 00003312 E8D7010000          <1> 	call	sp_init ; serial port initialization
  2134                              <1> 	; 14/08/2015
  2135 00003317 FB                  <1> 	sti
  2136                              <1> 	;
  2137                              <1> 	; 30/06/2015
  2138                              <1> 	;mov	esi, kernel_init_ok_msg
  2139                              <1> 	;call 	print_msg
  2140                              <1> 	;
  2141 00003318 30DB                <1> 	xor	bl, bl ; video page 0
  2142                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2143 0000331A E8400F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2144 0000331F FEC3                <1> 	inc	bl
  2145 00003321 80FB08              <1> 	cmp	bl, 8
  2146 00003324 72F4                <1> 	jb	short vp_clr_nxt
  2147                              <1> 	;
  2148                              <1> 	; 24/07/2015
  2149                              <1> 	;push	KDATA
  2150                              <1>         ;push	esp
  2151                              <1> 	;mov	[tss.esp0], esp
  2152                              <1>         ;mov	word [tss.ss0], KDATA
  2153                              <1> 	;
  2154                              <1> 	; 27/02/2022
  2155                              <1> 	; 24/08/2015
  2156                              <1> 	;; temporary (01/07/2015)
  2157                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2158                              <1> 			       ; it is not needed here !
  2159                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2160 00003326 FE0D[53700000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2161                              <1> 			      ; 0 = executing a system call
  2162                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2163                              <1> 	;
  2164                              <1> 	;;; 06/08/2015
  2165                              <1> 	;;;call	getch ; wait for a key stroke
  2166                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2167                              <1> ;;sys_init_msg_wait:
  2168                              <1> ;;	push 	ecx
  2169                              <1> ;;	mov	al, 1
  2170                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2171                              <1> ;;	call	getc_n
  2172                              <1> ;;	pop	ecx
  2173                              <1> ;;	jnz	short sys_init_msg_ok
  2174                              <1> ;;	loop	sys_init_msg_wait
  2175                              <1> 	;
  2176                              <1> ;;sys_init_msg_ok:
  2177                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2178 0000332C 6A10                <1> 	push	KDATA ; ss
  2179 0000332E 54                  <1> 	push	esp
  2180 0000332F 9C                  <1> 	pushfd
  2181 00003330 6A08                <1> 	push	KCODE ; cs
  2182 00003332 68[66330000]        <1> 	push	init_exec ; eip
  2183 00003337 8925[54700000]      <1> 	mov	[u.sp], esp
  2184 0000333D 1E                  <1> 	push	ds
  2185 0000333E 06                  <1> 	push	es
  2186 0000333F 0FA0                <1> 	push	fs
  2187 00003341 0FA8                <1> 	push	gs	
  2188 00003343 60                  <1> 	pushad
  2189 00003344 8925[58700000]      <1> 	mov	[u.usp], esp
  2190 0000334A E8B11B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2191                              <1> 		      ; and interrupt return components (for IRET)
  2192 0000334F 61                  <1> 	popad
  2193 00003350 6658                <1> 	pop	ax ; gs
  2194 00003352 6658                <1> 	pop	ax ; fs
  2195 00003354 6658                <1> 	pop	ax ; es
  2196 00003356 6658                <1> 	pop	ax ; ds	
  2197 00003358 58                  <1> 	pop	eax ; eip (init_exec)
  2198 00003359 6658                <1> 	pop	ax ; cs (KCODE)
  2199 0000335B 58                  <1> 	pop	eax ; E-FLAGS
  2200 0000335C 58                  <1> 	pop	eax ; esp
  2201 0000335D 6658                <1> 	pop	ax ; ss (KDATA)
  2202                              <1> 	;
  2203 0000335F 31C0                <1> 	xor	eax, eax ; 0
  2204 00003361 A3[B3700000]        <1> 	mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2205                              <1> 	;
  2206                              <1> 	; 02/07/2015
  2207                              <1> 	; [u.pgdir ] = [k_page_dir]
  2208                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2209                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2210                              <1> init_exec:
  2211                              <1> 	; 13/03/2013
  2212                              <1> 	; 24/07/2013
  2213 00003366 BB[88330000]        <1> 	mov	ebx, init_file
  2214 0000336B B9[80330000]        <1> 	mov	ecx, init_argp
  2215                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2216                              <1> 	; ECX contains address of argument list pointer
  2217                              <1> 	;
  2218                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2219                              <1> 			      ; 0 = executing a system call
  2220                              <1> 	sys	_exec  ; execute file
  2148                              <2> 
  2149                              <2> 
  2150 00003370 B80B000000          <2>  mov eax, %1
  2151                              <2>  %if %0 >= 2
  2152                              <2>  mov ebx, %2
  2153                              <2>  %if %0 >= 3
  2154                              <2>  mov ecx, %3
  2155                              <2>  %if %0 = 4
  2156                              <2>  mov edx, %4
  2157                              <2>  %endif
  2158                              <2>  %endif
  2159                              <2>  %endif
  2160 00003375 CD30                <2>  int 30h
  2221 00003377 7319                <1> 	jnc	short panic
  2222                              <1> 	;
  2223 00003379 BE[AA690000]        <1> 	mov	esi, etc_init_err_msg
  2224                              <1> 	; 27/02/2022
  2225                              <1> 	;call 	print_msg
  2226 0000337E EB17                <1> 	jmp	short key_to_reboot
  2227                              <1> 
  2228                              <1> ;align 4
  2229                              <1> init_argp:
  2230 00003380 [88330000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2231                              <1> init_file:
  2232                              <1> 	; 24/08/2015
  2233 00003388 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2233 00003391 00                  <1>
  2234                              <1> panic:
  2235                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2236                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2237 00003392 BE[8F690000]        <1> 	mov 	esi, panic_msg
  2238                              <1> key_to_reboot: ; 27/02/2022
  2239 00003397 E819000000          <1> 	call 	print_msg
  2240                              <1> ;key_to_reboot:
  2241                              <1> 	; 15/11/2015
  2242 0000339C E8102D0000          <1> 	call 	getch 
  2243                              <1> 		; wait for a character from the current tty
  2244                              <1> 	;
  2245 000033A1 B00A                <1> 	mov	al, 0Ah
  2246 000033A3 8A1D[C66C0000]      <1> 	mov	bl, [ptty] ; [active_page]
  2247 000033A9 B407                <1> 	mov	ah, 07h ; Black background, 
  2248                              <1> 			; light gray forecolor
  2249 000033AB E82AE0FFFF          <1> 	call 	write_tty
  2250 000033B0 E9C9DCFFFF          <1> 	jmp	cpu_reset 
  2251                              <1> 
  2252                              <1> print_msg:
  2253                              <1> 	; 01/07/2015
  2254                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2255                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2256                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2257                              <1> 	;
  2258                              <1> 	;
  2259 000033B5 AC                  <1> 	lodsb
  2260                              <1> pmsg1:
  2261 000033B6 56                  <1> 	push 	esi
  2262 000033B7 0FB61D[C66C0000]    <1> 	movzx	ebx, byte [ptty]
  2263 000033BE B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2264 000033C0 E815E0FFFF          <1> 	call 	write_tty
  2265 000033C5 5E                  <1> 	pop	esi
  2266 000033C6 AC                  <1> 	lodsb
  2267 000033C7 20C0                <1> 	and 	al, al
  2268 000033C9 75EB                <1> 	jnz 	short pmsg1
  2269 000033CB C3                  <1> 	retn
  2270                              <1> 	
  2271                              <1> ctrlbrk:
  2272                              <1> 	; 04/02/2022
  2273                              <1> 	; 01/02/2022
  2274                              <1> 	; 12/11/2015
  2275                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2276                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2277                              <1> 	;
  2278                              <1> 	; INT 1Bh (control+break) handler
  2279                              <1> 	;
  2280                              <1>       	; Retro Unix 8086 v1 feature only!
  2281                              <1>       	;
  2282 000033CC 66833D[9A700000]00  <1> 	cmp 	word [u.intr], 0
  2283 000033D4 764B                <1> 	jna 	short cbrk4
  2284                              <1> cbrk0:
  2285                              <1> 	; 12/11/2015
  2286                              <1> 	; 06/12/2013
  2287 000033D6 66833D[9C700000]00  <1> 	cmp 	word [u.quit], 0
  2288 000033DE 7441                <1> 	jz	short cbrk4
  2289                              <1> 	;
  2290                              <1> 	; 20/09/2013	
  2291                              <1> 	;push 	ax
  2292                              <1> 	; 01/02/2022
  2293 000033E0 50                  <1> 	push	eax
  2294                              <1> 
  2295                              <1> 	; 04/02/2022
  2296                              <1> 	; (repetitive ctrl+brk check) 
  2297 000033E1 66A1[9C700000]      <1> 	mov	ax, [u.quit]
  2298 000033E7 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2299 000033E9 7435                <1> 	jz	short cbrk3
  2300                              <1> 
  2301                              <1> 	; 20/09/2013
  2302 000033EB A0[C66C0000]        <1> 	mov	al, [ptty]
  2303                              <1> 	;
  2304                              <1> 	; 12/11/2015
  2305                              <1> 	;
  2306                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2307                              <1> 	; or ctrl+break from console (pseudo) tty
  2308                              <1> 	; (!redirection!)
  2309                              <1> 	;
  2310 000033F0 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2311 000033F2 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2312                              <1> 	;	
  2313                              <1> 	; Serial port interrupt handler sets [ptty]
  2314                              <1> 	; to the port's tty number (as temporary).
  2315                              <1> 	;
  2316                              <1> 	; If active process is using a stdin or 
  2317                              <1> 	; stdout redirection (by the shell),
  2318                              <1>         ; console tty keyboard must be available
  2319                              <1> 	; to terminate running process,
  2320                              <1> 	; in order to prevent a deadlock. 
  2321                              <1> 	;
  2322 000033F4 52                  <1> 	push	edx
  2323 000033F5 0FB615[A5700000]    <1> 	movzx	edx, byte [u.uno]
  2324 000033FC 3A82[B76D0000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2325 00003402 5A                  <1> 	pop	edx
  2326 00003403 7412                <1> 	je	short cbrk2
  2327                              <1> cbrk1:
  2328 00003405 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2329                              <1> 	; 06/12/2013
  2330 00003407 3A05[8C700000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2331 0000340D 7408                <1> 	je	short cbrk2	
  2332 0000340F 3A05[8D700000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2333 00003415 7509                <1> 	jne	short cbrk3	
  2334                              <1> cbrk2:
  2335                              <1> 	;; 06/12/2013
  2336                              <1> 	;mov	ax, [u.quit]
  2337                              <1> 	;and	ax, ax
  2338                              <1> 	;jz	short cbrk3
  2339                              <1> 	;
  2340                              <1> 	;xor	ax, ax ; 0
  2341                              <1> 	;dec	ax
  2342                              <1> 	; 01/02/2022
  2343 00003417 31C0                <1> 	xor	eax, eax ; 0
  2344 00003419 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2345                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2346 0000341A 66A3[9C700000]      <1> 	mov	[u.quit], ax
  2347                              <1> cbrk3:
  2348                              <1> 	;pop	ax
  2349                              <1> 	; 01/02/2022
  2350 00003420 58                  <1> 	pop	eax
  2351                              <1> cbrk4:
  2352 00003421 C3                  <1> 	retn
  2353                              <1> 
  2354                              <1> com2_int:
  2355                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2356                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2357                              <1> 	; 07/11/2015 
  2358                              <1> 	; 24/10/2015
  2359                              <1> 	; 23/10/2015
  2360                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2361                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2362                              <1> 	; < serial port 2 interrupt handler >
  2363                              <1> 	;
  2364 00003422 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2365                              <1> 	;;push	eax
  2366                              <1> 	; 08/01/2022
  2367 00003425 29C0                <1> 	sub	eax, eax
  2368 00003427 B009                <1> 	mov	al, 9
  2369                              <1> 	;mov	ax, 9
  2370 00003429 EB07                <1> 	jmp	short comm_int
  2371                              <1> com1_int:
  2372                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2373                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2374                              <1> 	; 07/11/2015
  2375                              <1> 	; 24/10/2015
  2376 0000342B 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2377                              <1> 	; 23/10/2015
  2378                              <1> 	;push	eax
  2379                              <1> 	; 08/01/2022
  2380 0000342E 29C0                <1> 	sub	eax, eax
  2381 00003430 B008                <1> 	mov	al, 8
  2382                              <1> 	;mov	ax, 8
  2383                              <1> comm_int:
  2384                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2385                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2386                              <1> 	; 20/11/2015
  2387                              <1> 	; 18/11/2015
  2388                              <1> 	; 17/11/2015
  2389                              <1> 	; 16/11/2015
  2390                              <1> 	; 09/11/2015
  2391                              <1> 	; 08/11/2015
  2392                              <1> 	; 07/11/2015
  2393                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2394                              <1> 	; 01/11/2015
  2395                              <1> 	; 26/10/2015
  2396                              <1> 	; 23/10/2015
  2397 00003432 53                  <1> 	push	ebx
  2398 00003433 56                  <1> 	push	esi
  2399 00003434 57                  <1> 	push	edi
  2400 00003435 1E                  <1> 	push 	ds
  2401 00003436 06                  <1> 	push 	es
  2402                              <1> 	; 18/11/2015
  2403 00003437 0F20DB              <1> 	mov	ebx, cr3
  2404 0000343A 53                  <1> 	push	ebx ; ****
  2405                              <1> 	;
  2406 0000343B 51                  <1> 	push	ecx ; ***
  2407 0000343C 52                  <1> 	push	edx ; **
  2408                              <1> 	;
  2409 0000343D BB10000000          <1> 	mov	ebx, KDATA
  2410 00003442 8EDB                <1> 	mov	ds, bx
  2411 00003444 8EC3                <1> 	mov	es, bx
  2412                              <1> 	;
  2413 00003446 8B0D[986C0000]      <1> 	mov	ecx, [k_page_dir]
  2414 0000344C 0F22D9              <1> 	mov	cr3, ecx
  2415                              <1> 	; 20/11/2015
  2416                              <1> 	; Interrupt identification register
  2417 0000344F 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2418                              <1> 	;
  2419 00003453 3C08                <1> 	cmp 	al, 8 
  2420 00003455 7702                <1> 	ja 	short com_i0
  2421                              <1> 	;
  2422                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2423                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2424                              <1> 	; 20/11/2015
  2425                              <1> 	; 17/11/2015
  2426                              <1> 	; 16/11/2015
  2427                              <1> 	; 15/11/2015
  2428                              <1> 	; 24/10/2015
  2429                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2430                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2431                              <1> 	; < serial port 1 interrupt handler >
  2432                              <1> 	;
  2433 00003457 FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2434                              <1> com_i0:
  2435                              <1> 	;push	eax ; *
  2436                              <1> 	; 07/11/2015
  2437 00003459 A2[066D0000]        <1> 	mov 	byte [ccomport], al
  2438                              <1> 	; 09/11/2015
  2439                              <1> 	;movzx	ebx, ax ; 8 or 9
  2440                              <1> 	; 08/01/2022
  2441 0000345E 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2442                              <1> 	; 17/11/2015
  2443                              <1>  	; reset request for response status
  2444 00003460 88A3[FC6C0000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2445                              <1> 	;
  2446                              <1> 	; 20/11/2015
  2447 00003466 EC                  <1> 	in	al, dx		; read interrupt id. register
  2448 00003467 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2449 00003469 2404                <1> 	and	al, 4		; received data available?	
  2450 0000346B 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2451                              <1> 	;
  2452                              <1> 	; 20/11/2015
  2453 0000346D 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2454 00003470 EC                  <1> 	in	al, dx     	; read character
  2455                              <1> 	;JMP	$+2	   	; I/O DELAY
  2456                              <1> 	; 08/11/2015
  2457                              <1> 	; 07/11/2015
  2458 00003471 89DE                <1> 	mov	esi, ebx 
  2459 00003473 89DF                <1> 	mov	edi, ebx
  2460 00003475 81C6[006D0000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2461 0000347B 81C7[026D0000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2462 00003481 8806                <1> 	mov	[esi], al ; received char (current char)
  2463                              <1> 	; query
  2464 00003483 20C0                <1> 	and	al, al
  2465 00003485 7527                <1> 	jnz	short com_i2
  2466                              <1>    	; response
  2467                              <1> 	; 17/11/2015
  2468                              <1> 	; set request for response status
  2469 00003487 FE83[FC6C0000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2470                              <1> 	;
  2471 0000348D 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2472 00003491 EC                  <1> 	in	al, dx	   	; read line status register 
  2473 00003492 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2474 00003494 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2475 00003496 7445                <1> 	jz	short com_eoi 	; no
  2476 00003498 B0FF                <1> 	mov 	al, 0FFh   	; response			
  2477 0000349A 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2478 0000349E EE                  <1> 	out	dx, al	   	; send on serial port
  2479                              <1> 	; 17/11/2015
  2480 0000349F 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2481 000034A2 7502                <1> 	jne 	short com_i1    ; no
  2482 000034A4 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2483                              <1> com_i1:
  2484                              <1> 	; 17/11/2015
  2485                              <1> 	; reset request for response status (again)
  2486 000034A6 FE8B[FC6C0000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2487 000034AC EB2F                <1> 	jmp	short com_eoi
  2488                              <1> com_i2:	
  2489                              <1> 	; 08/11/2015
  2490 000034AE 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2491 000034B0 7417                <1> 	je	short com_i3	; (check for response signal)
  2492                              <1> 	; 07/11/2015
  2493 000034B2 3C04                <1> 	cmp	al, 04h	; EOT
  2494 000034B4 751C                <1> 	jne	short com_i4	
  2495                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2496                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2497                              <1> 	; 08/11/2015
  2498                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2499 000034B6 861D[C66C0000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2500 000034BC E80BFFFFFF          <1> 	call 	ctrlbrk
  2501 000034C1 861D[C66C0000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2502                              <1> 	;mov	al, 04h ; EOT
  2503                              <1> 	; 08/11/2015
  2504 000034C7 EB09                <1> 	jmp	short com_i4	
  2505                              <1> com_i3:
  2506                              <1> 	; 08/11/2015
  2507                              <1> 	; If 0FFh has been received just after a query
  2508                              <1> 	; (schar, ZERO), it is a response signal.
  2509                              <1> 	; 17/11/2015
  2510 000034C9 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2511 000034CC 7704                <1> 	ja	short com_i4 ; no
  2512                              <1> 	; reset query status (schar)
  2513 000034CE 8807                <1> 	mov	[edi], al ; 0FFh
  2514 000034D0 FEC0                <1> 	inc	al ; 0
  2515                              <1> com_i4:
  2516                              <1> 	; 27/07/2014
  2517                              <1> 	; 09/07/2014
  2518 000034D2 D0E3                <1> 	shl	bl, 1	
  2519 000034D4 81C3[C86C0000]      <1> 	add	ebx, ttychr
  2520                              <1> 	; 23/07/2014 (always overwrite)
  2521                              <1> 	;;cmp	word [ebx], 0
  2522                              <1> 	;;ja	short com_eoi
  2523                              <1> 	;
  2524 000034DA 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2525                              <1> 			    ; scan code = 0
  2526                              <1> com_eoi:
  2527                              <1> 	;mov	al, 20h
  2528                              <1> 	;out	20h, al	   ; end of interrupt
  2529                              <1> 	;
  2530                              <1> 	; 07/11/2015
  2531                              <1>       	;pop	eax ; *
  2532 000034DD A0[066D0000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2533                              <1> 	; al = tty number (8 or 9)
  2534 000034E2 E8F31A0000          <1>         call	wakeup
  2535                              <1> com_iret:
  2536                              <1> 	; 23/10/2015
  2537 000034E7 5A                  <1> 	pop	edx ; **
  2538 000034E8 59                  <1> 	pop	ecx ; ***
  2539                              <1> 	; 18/11/2015
  2540                              <1> 	;pop	eax ; ****
  2541                              <1> 	;mov	cr3, eax
  2542                              <1> 	;jmp	iiret
  2543 000034E9 E9CCD4FFFF          <1> 	jmp	iiretp
  2544                              <1> 
  2545                              <1> ;hfgchr:
  2546                              <1> ;	db '0123456789ABCDEF?*'
  2547                              <1> ;	db 0
  2548                              <1> 
  2549                              <1> ;iiretp: ; 01/09/2015
  2550                              <1> ;	; 28/08/2015
  2551                              <1> ;	pop	eax ; (*) page directory
  2552                              <1> ;	mov	cr3, eax
  2553                              <1> ;iiret:
  2554                              <1> ;	; 22/08/2014
  2555                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2556                              <1> ;	out	20h, al	; 8259 PORT
  2557                              <1> ;	;
  2558                              <1> ;	pop	es
  2559                              <1> ;	pop	ds
  2560                              <1> ;	pop	edi
  2561                              <1> ;	pop	esi
  2562                              <1> ;	pop	ebx ; 29/08/2014
  2563                              <1> ;	pop 	eax
  2564                              <1> ;	iretd
  2565                              <1> 
  2566                              <1> sp_init:
  2567                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2568                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2569                              <1> 	; 07/11/2015
  2570                              <1> 	; 29/10/2015
  2571                              <1> 	; 26/10/2015
  2572                              <1> 	; 23/10/2015
  2573                              <1> 	; 29/06/2015
  2574                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2575                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2576                              <1> 	; Initialization of Serial Port Communication Parameters
  2577                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2578                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2579                              <1> 	;
  2580                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2581                              <1> 	;
  2582                              <1> 	; INPUT:  (29/06/2015)
  2583                              <1> 	;	AL = 0 for COM1
  2584                              <1> 	;	     1 for COM2
  2585                              <1> 	;	AH = Communication parameters	
  2586                              <1> 	;
  2587                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2588                              <1> 	;	Bit	4	3	2	1	0
  2589                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2590                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2591                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2592                              <1> 	;		11 = even
  2593                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2594                              <1> 	;		Retro UNIX 386 v1 feature only !
  2595                              <1> 	;	Bit	7    6    5  | Baud rate
  2596                              <1> 	;		------------------------
  2597                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2598                              <1> 	;		0    0    1  | 9600 (12)
  2599                              <1> 	;		0    1    0  | 19200 (6) 
  2600                              <1> 	;		0    1	  1  | 38400 (3) 
  2601                              <1> 	;		1    0	  0  | 14400 (8)
  2602                              <1> 	;		1    0	  1  | 28800 (4)
  2603                              <1> 	;		1    1    0  | 57600 (2)
  2604                              <1> 	;		1    1    1  | 115200 (1) 	
  2605                              <1> 	
  2606                              <1> 	; References:	
  2607                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2608                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2609                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2610                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2611                              <1> 	;
  2612                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2613                              <1> 	;
  2614 000034EE BB[026D0000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2615 000034F3 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2616                              <1> 	; 29/10/2015
  2617 000034F7 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2618 000034FB E84F000000          <1> 	call	sp_i3	; call A4	
  2619 00003500 A880                <1> 	test	al, 80h
  2620 00003502 740E                <1> 	jz	short sp_i0 ; OK..
  2621                              <1> 		; Error !
  2622                              <1> 	;mov	dx, 3F8h
  2623 00003504 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2624                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2625                              <1> 	; 08/01/2022
  2626 00003507 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2627 00003509 E841000000          <1> 	call	sp_i3	; call A4	
  2628 0000350E A880                <1> 	test	al, 80h
  2629 00003510 7508                <1> 	jnz	short sp_i1
  2630                              <1> sp_i0:
  2631                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2632                              <1>         ; (INT 14h initialization code disables interrupts.)
  2633                              <1> 	;
  2634 00003512 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2635 00003515 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2636                              <1> sp_i1:
  2637 0000351A 43                  <1> 	inc	ebx
  2638 0000351B 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2639                              <1> 	; 29/10/2015
  2640                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2641                              <1> 	; 08/01/2022
  2642 0000351F B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2643 00003521 E829000000          <1> 	call	sp_i3	; call A4	
  2644 00003526 A880                <1> 	test	al, 80h
  2645 00003528 740E                <1> 	jz	short sp_i2 ; OK..
  2646                              <1> 		; Error !
  2647                              <1> 	;mov	dx, 2F8h
  2648 0000352A 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2649                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2650                              <1> 	; 08/01/2022
  2651 0000352D B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2652 0000352F E81B000000          <1> 	call	sp_i3	; call A4	
  2653 00003534 A880                <1> 	test	al, 80h
  2654 00003536 7516                <1> 	jnz	short sp_i7
  2655                              <1> sp_i2:
  2656 00003538 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2657                              <1> sp_i6:
  2658                              <1> 	;; COM2 - enabling IRQ 3
  2659                              <1> 	; 08/01/2022
  2660 0000353B B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2661                              <1> 	; 07/11/2015
  2662                              <1> 	; 26/10/2015
  2663                              <1> 	;pushf
  2664                              <1> 	;cli
  2665                              <1> 	;;
  2666                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2667                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2668                              <1> 	;in	al, dx 	   		; read register
  2669                              <1> 	;JMP	$+2	   		; I/O DELAY
  2670                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2671                              <1> 	;out	dx, al     		; write back to register
  2672                              <1> 	;JMP	$+2	   		; I/O DELAY
  2673                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2674                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2675                              <1> 	;in	al, dx     		; read register
  2676                              <1> 	;JMP	$+2	   		; I/O DELAY
  2677                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2678                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2679                              <1> 	;out	dx, al 	   		; write back to register
  2680                              <1> 	;JMP	$+2        		; I/O DELAY
  2681                              <1> 	;in	al, 21h    		; read interrupt mask register
  2682                              <1> 	;JMP	$+2	   		; I/O DELAY
  2683                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2684                              <1> 	;out	21h, al    		; write back to register
  2685                              <1> 	;
  2686                              <1> 	; 08/01/2022
  2687 0000353D 9C                  <1> 	pushf
  2688 0000353E E8AA000000          <1> 	call	sp_i8
  2689                              <1> 	; 23/10/2015
  2690 00003543 B8[22340000]        <1> 	mov 	eax, com2_int
  2691 00003548 A3[D6390000]        <1> 	mov	[com2_irq3], eax
  2692                              <1> 	; 26/10/2015
  2693 0000354D 9D                  <1> 	popf	
  2694                              <1> sp_i7:
  2695 0000354E C3                  <1> 	retn
  2696                              <1> 
  2697                              <1> sp_i3:
  2698                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2699                              <1> 	; 28/10/2015
  2700 0000354F FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2701 00003551 B000                <1> 	mov	al, 0
  2702 00003553 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2703 00003554 EB00                <1> 	JMP	$+2			; I/O DELAY
  2704 00003556 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2705 00003559 B080                <1> 	mov	al, 80h			
  2706 0000355B EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2707                              <1> 	;-----	SET BAUD RATE DIVISOR
  2708                              <1> 	; 26/10/2015
  2709 0000355C 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2710                              <1> 					; of the divisor value
  2711 0000355F 88C8                <1> 	mov	al, cl	; 1
  2712 00003561 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2713                              <1> 					; 2 = 57600 baud
  2714                              <1> 					; 3 = 38400 baud
  2715                              <1> 					; 6 = 19200 baud
  2716                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2717 00003562 EB00                <1> 	JMP	$+2			; I/O DELAY
  2718 00003564 28C0                <1> 	sub	al, al
  2719 00003566 FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2720                              <1> 					; of the divisor value
  2721 00003568 EE                  <1> 	out	dx, al ; 0
  2722 00003569 EB00                <1> 	JMP	$+2			; I/O DELAY
  2723                              <1> 	;	
  2724 0000356B 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2725                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2726 0000356D 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2727 00003570 EE                  <1> 	out	dx, al			
  2728 00003571 EB00                <1> 	JMP	$+2			; I/O DELAY
  2729                              <1> 	; 29/10/2015
  2730 00003573 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2731 00003575 30C0                <1> 	xor	al, al			; 0
  2732 00003577 EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2733 00003578 EB00                <1> 	JMP	$+2	
  2734                              <1> sp_i4:
  2735                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2736                              <1> 	; 29/06/2015 (line status after modem status)
  2737 0000357A 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2738                              <1> sp_i4s:
  2739 0000357D EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2740 0000357E EB00                <1> 	JMP	$+2			; I/O DELAY
  2741 00003580 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2742 00003582 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2743                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2744 00003584 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2745                              <1> 	; AL = Line status, AH = Modem status
  2746 00003585 C3                  <1> 	retn
  2747                              <1> 
  2748                              <1> sp_status:
  2749                              <1> 	; 29/06/2015
  2750                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2751                              <1> 	; Get serial port status
  2752 00003586 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2753 0000358A 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2754                              <1> 					; dx = 2FEh for COM2
  2755 0000358C EBEF                <1> 	jmp	short sp_i4s
  2756                              <1> 
  2757                              <1> sp_setp: ; Set serial port communication parameters
  2758                              <1> 	; 04/02/2022 
  2759                              <1> 	;	(Retro UNIX 386 v1, Kernel v0.2.0.18)
  2760                              <1> 	; 08/01/2022
  2761                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2762                              <1> 	; 07/11/2015
  2763                              <1> 	; 29/10/2015
  2764                              <1> 	; 29/06/2015
  2765                              <1> 	; Retro UNIX 386 v1 feature only !	
  2766                              <1> 	;
  2767                              <1> 	; INPUT:
  2768                              <1> 	;	AL = 0 for COM1
  2769                              <1> 	;	     1 for COM2
  2770                              <1> 	;	AH = Communication parameters (*)
  2771                              <1> 	; OUTPUT:
  2772                              <1> 	;	CL = Line status
  2773                              <1> 	;	CH = Modem status
  2774                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2775                              <1> 	;		 'invalid parameter !' 
  2776                              <1> 	;		 	 or
  2777                              <1> 	;		 'device not ready !' error
  2778                              <1> 	;	
  2779                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2780                              <1> 	;	Bit	4	3	2	1	0
  2781                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2782                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2783                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2784                              <1> 	;		11 = even
  2785                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2786                              <1> 	;		Retro UNIX 386 v1 feature only !
  2787                              <1> 	;	Bit	7    6    5  | Baud rate
  2788                              <1> 	;		------------------------
  2789                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2790                              <1> 	;		0    0    1  | 9600 (12)
  2791                              <1> 	;		0    1    0  | 19200 (6) 
  2792                              <1> 	;		0    1	  1  | 38400 (3) 
  2793                              <1> 	;		1    0	  0  | 14400 (8)
  2794                              <1> 	;		1    0	  1  | 28800 (4)
  2795                              <1> 	;		1    1    0  | 57600 (2)
  2796                              <1> 	;		1    1    1  | 115200 (1) 
  2797                              <1> 	;
  2798                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2799                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2800                              <1> 	;
  2801                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2802                              <1> 	;
  2803 0000358E 66BAF803            <1> 	mov	dx, 3F8h
  2804 00003592 BB[026D0000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2805 00003597 3C01                <1> 	cmp	al, 1
  2806 00003599 7770                <1> 	ja 	short sp_invp_err
  2807 0000359B 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2808 0000359D FECE                <1> 	dec	dh ; 2F8h
  2809 0000359F 43                  <1> 	inc	ebx ; COM2 control byte offset
  2810                              <1> sp_setp1:
  2811                              <1> 	; 29/10/2015
  2812 000035A0 8823                <1> 	mov	[ebx], ah
  2813 000035A2 0FB6CC              <1> 	movzx 	ecx, ah
  2814 000035A5 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2815 000035A8 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2816 000035AB 8A81[1A360000]      <1> 	mov	al, [ecx+b_div_tbl]
  2817 000035B1 6689C1              <1> 	mov	cx, ax
  2818 000035B4 E896FFFFFF          <1> 	call	sp_i3
  2819 000035B9 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2820 000035BC A880                <1> 	test	al, 80h
  2821 000035BE 740F                <1> 	jz	short sp_setp2
  2822 000035C0 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2823                              <1> stp_dnr_err:
  2824 000035C3 C705[AB700000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2824 000035CB 0000                <1>
  2825                              <1> 	; CL = Line status, CH = Modem status
  2826 000035CD F9                  <1> 	stc
  2827 000035CE C3                  <1> 	retn
  2828                              <1> sp_setp2:
  2829 000035CF 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2830                              <1>         ;jna	sp_i6
  2831                              <1> 		      ; COM1 (3F?h)
  2832                              <1> 	; 24/12/2021
  2833 000035D2 7705                <1> 	ja	short sp_i5
  2834 000035D4 E962FFFFFF          <1> 	jmp	sp_i6
  2835                              <1> sp_i5: 
  2836                              <1> 	; 08/01/2022
  2837 000035D9 B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2838                              <1> 	; 07/11/2015
  2839                              <1> 	; 26/10/2015
  2840                              <1> 	; 29/06/2015
  2841                              <1> 	;
  2842                              <1> 	;; COM1 - enabling IRQ 4
  2843                              <1> 	;pushf
  2844                              <1> 	;cli
  2845                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2846                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2847                              <1> 	;in	al, dx 	   		; read register
  2848                              <1> 	;JMP	$+2			; I/O DELAY
  2849                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2850                              <1> 	;out	dx, al     		; write back to register
  2851                              <1> 	;JMP	$+2			; I/O DELAY
  2852                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2853                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2854                              <1> 	;in	al, dx     		; read register
  2855                              <1> 	;JMP	$+2			; I/O DELAY
  2856                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2857                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2858                              <1> 	;out	dx, al 	   		; write back to register
  2859                              <1> 	;JMP	$+2        		; I/O DELAY
  2860                              <1> 	;in	al, 21h    		; read interrupt mask register
  2861                              <1> 	;JMP	$+2			; I/O DELAY
  2862                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2863                              <1> 	;out	21h, al    		; write back to register
  2864                              <1> 	;
  2865                              <1> 	; 08/01/2022
  2866 000035DB 9C                  <1> 	pushf
  2867 000035DC E80C000000          <1> 	call	sp_i8
  2868                              <1> 	; 23/10/2015
  2869 000035E1 B8[2B340000]        <1> 	mov 	eax, com1_int
  2870 000035E6 A3[D2390000]        <1> 	mov	[com1_irq4], eax
  2871                              <1> 	; 26/10/2015
  2872 000035EB 9D                  <1> 	popf
  2873 000035EC C3                  <1> 	retn
  2874                              <1> 
  2875                              <1> sp_i8:
  2876                              <1> 	; 08/01/2022
  2877                              <1> 	;pushf
  2878 000035ED FA                  <1> 	cli
  2879                              <1> 	;
  2880                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2881 000035EE B2FC                <1> 	mov	dl, 0FCh
  2882 000035F0 EC                  <1> 	in	al, dx 	   		; read register
  2883 000035F1 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2884 000035F3 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2885 000035F5 EE                  <1> 	out	dx, al     		; write back to register
  2886 000035F6 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2887                              <1> 	;mov	dx, 2F9h  ; 3F9h 		; interrupt enable register
  2888 000035F8 B2F9                <1> 	mov	dl, 0F9h
  2889 000035FA EC                  <1> 	in	al, dx     		; read register
  2890 000035FB EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2891                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2892 000035FD 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2893 000035FF EE                  <1> 	out	dx, al 	   		; write back to register
  2894 00003600 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2895 00003602 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2896 00003604 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2897                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2898 00003606 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2899 00003608 E621                <1> 	out	21h, al    		; write back to register
  2900                              <1> 	;
  2901                              <1> 	;popf	
  2902 0000360A C3                  <1> 	retn
  2903                              <1> 
  2904                              <1> sp_invp_err:
  2905 0000360B C705[AB700000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2905 00003613 0000                <1>
  2906 00003615 31C9                <1> 	xor	ecx, ecx
  2907 00003617 49                  <1> 	dec	ecx ; 0FFFFh
  2908 00003618 F9                  <1> 	stc
  2909 00003619 C3                  <1> 	retn
  2910                              <1> 
  2911                              <1> ; 29/10/2015
  2912                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2913 0000361A 010C0603080401      <1> 	db 1, 12, 6, 3, 8, 4, 1
  2914                              <1> 
  2915                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2916                              <1> epoch:
  2917                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2918                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2919                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2920                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2921                              <1> 	; 'epoch' procedure prototype: 
  2922                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2923                              <1> 	; 14/11/2012
  2924                              <1> 	; unixboot.asm (boot file configuration)
  2925                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2926                              <1> 	; 21/7/2012
  2927                              <1> 	; 15/7/2012
  2928                              <1> 	; 14/7/2012		
  2929                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2930                              <1> 	; compute current date and time as UNIX Epoch/Time
  2931                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2932                              <1> 	;
  2933                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2934                              <1> 	;
  2935 00003621 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2936 00003626 86E9                <1>         xchg 	ch,cl
  2937 00003628 66890D[026A0000]    <1>         mov 	[hour], cx
  2938 0000362F 86F2                <1>         xchg 	dh,dl
  2939 00003631 668915[046A0000]    <1>         mov 	[second], dx
  2940                              <1> 	;
  2941 00003638 E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2942 0000363D 86E9                <1>         xchg 	ch,cl
  2943 0000363F 66890D[FE690000]    <1>         mov 	[year], cx
  2944 00003646 86F2                <1>         xchg 	dh,dl
  2945 00003648 668915[006A0000]    <1>         mov 	[month], dx
  2946                              <1> 	;
  2947 0000364F 66B93030            <1> 	mov 	cx, 3030h
  2948                              <1> 	;
  2949 00003653 A0[026A0000]        <1> 	mov 	al, [hour] ; Hour
  2950                              <1>         	; AL <= BCD number)
  2951 00003658 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2952                              <1> 					; AH = AL / 10h
  2953                              <1> 					; AL = AL MOD 10h
  2954 0000365A D50A                <1>         aad 	; AX= AH*10+AL
  2955 0000365C A2[026A0000]        <1> 	mov 	[hour], al
  2956 00003661 A0[036A0000]        <1> 	mov 	al, [hour+1] ; Minute
  2957                              <1>         	; AL <= BCD number)
  2958 00003666 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2959                              <1> 					; AH = AL / 10h
  2960                              <1> 					; AL = AL MOD 10h
  2961 00003668 D50A                <1>         aad 	; AX= AH*10+AL
  2962 0000366A A2[036A0000]        <1> 	mov 	[minute], al
  2963 0000366F A0[046A0000]        <1> 	mov 	al, [second] ; Second
  2964                              <1>         	; AL <= BCD number)
  2965 00003674 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2966                              <1> 					; AH = AL / 10h
  2967                              <1> 					; AL = AL MOD 10h
  2968 00003676 D50A                <1>         aad 	; AX= AH*10+AL
  2969 00003678 A2[046A0000]        <1> 	mov 	[second], al
  2970 0000367D 66A1[FE690000]      <1> 	mov 	ax, [year] ; Year (century)
  2971                              <1>  	;push 	ax
  2972                              <1> 	; 08/01/2022
  2973 00003683 50                  <1> 	push	eax
  2974                              <1> 	   	; AL <= BCD number)
  2975 00003684 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2976                              <1> 					; AH = AL / 10h
  2977                              <1> 					; AL = AL MOD 10h
  2978 00003686 D50A                <1>         aad 	; AX= AH*10+AL
  2979 00003688 B464                <1> 	mov 	ah, 100
  2980 0000368A F6E4                <1> 	mul 	ah
  2981 0000368C 66A3[FE690000]      <1> 	mov 	[year], ax
  2982                              <1> 	;pop	ax
  2983                              <1> 	; 08/01/2022
  2984 00003692 58                  <1> 	pop	eax
  2985 00003693 88E0                <1> 	mov	al, ah
  2986                              <1>         	; AL <= BCD number)
  2987 00003695 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2988                              <1> 					; AH = AL / 10h
  2989                              <1> 					; AL = AL MOD 10h
  2990 00003697 D50A                <1>         aad 	; AX= AH*10+AL
  2991 00003699 660105[FE690000]    <1> 	add 	[year], ax
  2992 000036A0 A0[006A0000]        <1> 	mov 	al, [month] ; Month
  2993                              <1>            	; AL <= BCD number)
  2994 000036A5 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2995                              <1> 					; AH = AL / 10h
  2996                              <1> 					; AL = AL MOD 10h
  2997 000036A7 D50A                <1>         aad 	; AX= AH*10+AL
  2998 000036A9 A2[006A0000]        <1> 	mov 	[month], al	
  2999 000036AE A0[016A0000]        <1>         mov     al, [month+1]      	; Day
  3000                              <1>            	; AL <= BCD number)
  3001 000036B3 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3002                              <1> 					; AH = AL / 10h
  3003                              <1> 					; AL = AL MOD 10h
  3004 000036B5 D50A                <1>         aad 	; AX= AH*10+AL
  3005 000036B7 A2[016A0000]        <1>         mov     [day], al
  3006                              <1> 	
  3007                              <1> convert_to_epoch:
  3008                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3009                              <1> 	; 09/04/2013 (retro UNIX 8086 v1)
  3010                              <1> 	;
  3011                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3012                              <1> 	;
  3013                              <1> 	; Derived from DALLAS Semiconductor
  3014                              <1> 	; Application Note 31 (DS1602/DS1603)
  3015                              <1> 	; 6 May 1998
  3016 000036BC 29C0                <1> 	sub 	eax, eax
  3017 000036BE 66A1[FE690000]      <1> 	mov 	ax, [year]
  3018 000036C4 662DB207            <1> 	sub 	ax, 1970
  3019 000036C8 BA6D010000          <1> 	mov 	edx, 365
  3020 000036CD F7E2                <1> 	mul 	edx
  3021 000036CF 31DB                <1> 	xor 	ebx, ebx
  3022 000036D1 8A1D[006A0000]      <1> 	mov 	bl, [month]
  3023 000036D7 FECB                <1> 	dec 	bl
  3024 000036D9 D0E3                <1> 	shl 	bl, 1
  3025                              <1> 	;sub	edx, edx
  3026 000036DB 668B93[066A0000]    <1> 	mov 	dx, [EBX+DMonth]
  3027 000036E2 8A1D[016A0000]      <1>         mov     bl, [day]
  3028 000036E8 FECB                <1> 	dec 	bl
  3029 000036EA 01D0                <1> 	add 	eax, edx
  3030 000036EC 01D8                <1> 	add 	eax, ebx
  3031                              <1> 			; EAX = days since 1/1/1970
  3032 000036EE 668B15[FE690000]    <1> 	mov 	dx, [year]
  3033 000036F5 6681EAB107          <1> 	sub 	dx, 1969
  3034 000036FA 66D1EA              <1> 	shr 	dx, 1
  3035 000036FD 66D1EA              <1> 	shr 	dx, 1		
  3036                              <1> 		; (year-1969)/4
  3037 00003700 01D0                <1> 	add 	eax, edx
  3038                              <1> 			; + leap days since 1/1/1970
  3039 00003702 803D[006A0000]02    <1> 	cmp 	byte [month], 2	; if past february
  3040 00003709 7610                <1> 	jna 	short cte1
  3041 0000370B 668B15[FE690000]    <1> 	mov 	dx, [year]
  3042 00003712 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3043 00003716 7503                <1> 	jnz 	short cte1		
  3044                              <1> 			; and if leap year
  3045 00003718 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3046                              <1> cte1: 			; compute seconds since 1/1/1970
  3047 0000371B BA18000000          <1> 	mov 	edx, 24
  3048 00003720 F7E2                <1> 	mul	edx
  3049 00003722 8A15[026A0000]      <1> 	mov 	dl, [hour]
  3050 00003728 01D0                <1> 	add 	eax, edx
  3051                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3052                              <1> 	;mov	ebx, 60
  3053 0000372A B33C                <1> 	mov	bl, 60
  3054 0000372C F7E3                <1> 	mul	ebx
  3055 0000372E 8A15[036A0000]      <1> 	mov 	dl, [minute]
  3056 00003734 01D0                <1> 	add 	eax, edx
  3057                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3058                              <1> 	;mov 	ebx, 60
  3059 00003736 F7E3                <1> 	mul	ebx
  3060 00003738 8A15[046A0000]      <1> 	mov 	dl, [second]
  3061 0000373E 01D0                <1> 	add 	eax, edx
  3062                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3063 00003740 C3                  <1> 	retn
  3064                              <1> 
  3065                              <1> get_rtc_time:
  3066                              <1> 	; 15/03/2015
  3067                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	:
  3068                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	:
  3069                              <1> 	; INT 1Ah						:
  3070                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3071                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3072                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3073                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3074                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3075                              <1> 	;								
  3076                              <1> RTC_20: 			; GET RTC TIME
  3077 00003741 FA                  <1> 	cli
  3078 00003742 E811D4FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3079 00003747 7227                <1> 	JC	short RTC_29	; EXIT IF ERROR (CY= 1)
  3080                              <1> 
  3081 00003749 B000                <1> 	MOV	AL,CMOS_SECONDS ; SET ADDRESS OF SECONDS
  3082 0000374B E8F0D3FFFF          <1> 	CALL	CMOS_READ	; GET SECONDS
  3083 00003750 88C6                <1> 	MOV	DH,AL		; SAVE
  3084 00003752 B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3085 00003754 E8E7D3FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3086 00003759 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3087 0000375B 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3088 0000375D B002                <1> 	MOV	AL,CMOS_MINUTES ; SET ADDRESS OF MINUTES
  3089 0000375F E8DCD3FFFF          <1> 	CALL	CMOS_READ	; GET MINUTES
  3090 00003764 88C1                <1> 	MOV	CL,AL		; SAVE
  3091 00003766 B004                <1> 	MOV	AL,CMOS_HOURS	; SET ADDRESS OF HOURS
  3092 00003768 E8D3D3FFFF          <1> 	CALL	CMOS_READ	; GET HOURS
  3093 0000376D 88C5                <1> 	MOV	CH,AL		; SAVE
  3094 0000376F F8                  <1> 	CLC			; SET CY= 0
  3095                              <1> RTC_29:
  3096 00003770 FB                  <1> 	sti
  3097 00003771 C3                  <1> 	RETn			; RETURN WITH RESULT IN CARRY FLAG
  3098                              <1> 
  3099                              <1> get_rtc_date:
  3100                              <1> 	; 15/03/2015
  3101                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	       :
  3102                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	       :
  3103                              <1> 	; INT 1Ah						       :
  3104                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3105                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3106                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3107                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3108                              <1> 	;      (DL) = DAY IN BCD (01-31).			       :		
  3109                              <1> 	;
  3110                              <1> RTC_40: 			; GET RTC DATE
  3111 00003772 FA                  <1> 	cli
  3112 00003773 E8E0D3FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3113 00003778 7225                <1> 	JC	short RTC_49	; EXIT IF ERROR (CY= 1)
  3114                              <1> 
  3115 0000377A B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH
  3116 0000377C E8BFD3FFFF          <1> 	CALL	CMOS_READ	; READ DAY OF MONTH
  3117 00003781 88C2                <1> 	MOV	DL,AL		; SAVE
  3118 00003783 B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH
  3119 00003785 E8B6D3FFFF          <1> 	CALL	CMOS_READ	; READ MONTH
  3120 0000378A 88C6                <1> 	MOV	DH,AL		; SAVE
  3121 0000378C B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR
  3122 0000378E E8ADD3FFFF          <1> 	CALL	CMOS_READ	; READ YEAR
  3123 00003793 88C1                <1> 	MOV	CL,AL		; SAVE
  3124 00003795 B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY LOCATION
  3125 00003797 E8A4D3FFFF          <1> 	CALL	CMOS_READ	; GET CENTURY BYTE
  3126 0000379C 88C5                <1> 	MOV	CH,AL		; SAVE
  3127 0000379E F8                  <1> 	CLC			; SET CY=0
  3128                              <1> RTC_49:
  3129 0000379F FB                  <1> 	sti
  3130 000037A0 C3                  <1> 	RETn			; RETURN WITH RESULTS IN CARRY FLAG
  3131                              <1> 
  3132                              <1> set_date_time:
  3133                              <1> convert_from_epoch:
  3134                              <1> 	; 02/06/2022
  3135                              <1> 	; 01/06/2022 (BugFix)
  3136                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3137                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3138                              <1> 	; 'convert_from_epoch' procedure prototype:
  3139                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3140                              <1> 	;
  3141                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))
  3142                              <1> 	;
  3143                              <1> 	; Derived from DALLAS Semiconductor
  3144                              <1> 	; Application Note 31 (DS1602/DS1603)
  3145                              <1> 	; 6 May 1998
  3146                              <1> 	;
  3147                              <1> 	; INPUT:
  3148                              <1> 	; EAX = Unix (Epoch) Time
  3149                              <1> 	;
  3150 000037A1 31D2                <1> 	xor 	edx, edx
  3151                              <1> 	; 02/06/2022
  3152 000037A3 31C9                <1> 	xor	ecx, ecx
  3153 000037A5 31DB                <1> 	xor	ebx, ebx
  3154                              <1> 	;mov 	ecx, 60
  3155 000037A7 B13C                <1> 	mov	cl, 60
  3156 000037A9 F7F1                <1> 	div	ecx
  3157                              <1> 	;mov 	[imin], eax  ; whole minutes
  3158                              <1> 			     ; since 1/1/1970
  3159                              <1> 	;mov 	[second], dx ; leftover seconds
  3160 000037AB 8815[046A0000]      <1> 	mov	[second], dl ; 02/06/2022
  3161 000037B1 29D2                <1> 	sub 	edx, edx
  3162 000037B3 F7F1                <1> 	div	ecx
  3163                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3164                              <1> 	;		     ; since 1/1/1970
  3165                              <1> 	;mov 	[minute], dx ; leftover minutes
  3166 000037B5 8815[036A0000]      <1> 	mov	[minute], dl ; 02/06/2022
  3167 000037BB 31D2                <1> 	xor	edx, edx
  3168                              <1> 	;mov 	cx, 24
  3169 000037BD B118                <1> 	mov 	cl, 24
  3170 000037BF F7F1                <1> 	div	ecx
  3171                              <1> 	;mov 	[iday], ax   ; whole days
  3172                              <1> 			     ; since 1/1/1970
  3173                              <1> 	;mov 	[hour], dx   ; leftover hours
  3174 000037C1 8815[026A0000]      <1> 	mov	[hour], dl   ; 02/06/2022
  3175                              <1> 
  3176 000037C7 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3177                              <1> 			     ; 1/1/1968 	
  3178                              <1> 	;mov 	[iday], ax
  3179 000037CC 50                  <1> 	push 	eax
  3180 000037CD 29D2                <1> 	sub	edx, edx
  3181 000037CF B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3182 000037D4 F7F1                <1> 	div	ecx
  3183 000037D6 59                  <1> 	pop 	ecx
  3184                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3185                              <1> 	;push	dx
  3186                              <1> 	; 01/06/2022
  3187 000037D7 52                  <1> 	push 	edx
  3188                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3189 000037D8 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3190 000037DC F5                  <1> 	cmc		     ; add this quadyr's leap day
  3191 000037DD 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3192                              <1> 	;mov 	[lday], ax   ; since 1968
  3193                              <1> 	;mov 	cx, [iday]
  3194 000037E0 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday
  3195 000037E1 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3196 000037E3 B96D010000          <1> 	mov 	ecx, 365
  3197 000037E8 31D2                <1> 	xor	edx, edx
  3198                              <1> 	; EAX = iday-lday, EDX = 0
  3199 000037EA F7F1                <1> 	div	ecx
  3200                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3201                              <1> 	;jday = iday - (iyrs*365) - lday
  3202                              <1> 	;mov	[jday], dx   ; days since 1/1 of current year
  3203                              <1> 	;add	eax, 1968
  3204 000037EC 6605B007            <1> 	add 	ax, 1968     ; compute year
  3205 000037F0 66A3[FE690000]      <1> 	mov 	[year], ax
  3206                              <1> 	;mov 	cx, dx
  3207                              <1> 	; 02/06/2022
  3208 000037F6 89D1                <1> 	mov	ecx, edx
  3209                              <1> 	;mov 	dx, [qday]
  3210                              <1> 	;pop	dx
  3211                              <1> 	; 01/06/2022
  3212 000037F8 5A                  <1> 	pop 	edx
  3213 000037F9 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3214 000037FE 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3215 00003800 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3216 00003804 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3217 00003805 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3218                              <1> cfe1:			
  3219                              <1> 	;mov 	[jday], cx
  3220                              <1> 	;mov 	bx, 12       ; estimate month
  3221                              <1> 	;sub	ebx, ebx
  3222                              <1> 	; 02/06/2022
  3223 00003809 B30C                <1> 	mov	bl, 12
  3224 0000380B 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3225 0000380F 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3226                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3227                              <1> 	;cmp 	cx, dx       ; mday = # of days passed from 1/1
  3228                              <1> 	; 02/06/2022
  3229 00003813 39D1                <1> 	cmp	ecx, edx 	 		
  3230 00003815 7319                <1> 	jnb 	short cfe3
  3231                              <1> 	;dec 	bx           ; month = month - 1
  3232 00003817 FECB                <1> 	dec	bl			
  3233                              <1> 	;shl 	bx, 1
  3234 00003819 D0E3                <1> 	shl	bl, 1
  3235 0000381B 668B93[066A0000]    <1> 	mov 	dx, [ebx+DMonth] ; # elapsed days at 1st of month
  3236                              <1> 	;shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3237                              <1> 	; 02/06/2022
  3238 00003822 D0EB                <1> 	shr	bl, 1
  3239 00003824 80FB01              <1> 	cmp	bl, 1
  3240                              <1> 	;cmp	bx, 1        ; if month > 2 and year mod 4  = 0
  3241 00003827 76EA                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3242 00003829 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3243 0000382B 75E6                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3244                              <1> 	;inc 	dx           ; mday = mday + 1
  3245 0000382D 42                  <1> 	inc	edx
  3246 0000382E EBE3                <1> 	jmp 	short cfe2
  3247                              <1> cfe3:
  3248                              <1> 	;inc 	bx	     ; -> bx = month, 1 to 12
  3249                              <1> 	; 02/06/2022
  3250 00003830 FEC3                <1> 	inc	bl
  3251                              <1> 	;mov 	[month], bx
  3252 00003832 881D[006A0000]      <1> 	mov	[month], bl
  3253                              <1> 	;sub 	cx, dx	     ; day = jday - mday + 1
  3254 00003838 29D1                <1> 	sub	ecx, edx
  3255                              <1> 	;inc 	cx
  3256 0000383A FEC1                <1> 	inc	cl
  3257                              <1> 	;mov 	[day], cx
  3258 0000383C 880D[016A0000]      <1> 	mov	[day], cl    ; 02/06/2022
  3259                              <1> 	
  3260                              <1> 	; eax, ebx, ecx, edx is changed at return
  3261                              <1> 	; output ->
  3262                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3263                              <1> 	
  3264                              <1> 	; 01/06/2022 (BugFix)
  3265                              <1> _set_date:
  3266 00003842 66A1[FE690000]      <1> 	mov	ax, [year]
  3267 00003848 B520                <1> 	mov	ch, 20h ; century (bcd)
  3268 0000384A 662DD007            <1> 	sub	ax, 2000
  3269 0000384E 7306                <1> 	jnc	short set_date
  3270 00003850 B519                <1> 	mov	ch, 19h ; century (bcd) 
  3271 00003852 6683C064            <1> 	add	ax, 100	
  3272                              <1> 	; 01/06/2022
  3273                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3274                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3275                              <1> set_date:
  3276                              <1>         ;mov	al, [year+1]
  3277                              <1> 	;aam 	; ah = al / 10, al = al mod 10
  3278                              <1> 	;db 	0D5h, 10h    ; Undocumented inst. AAD
  3279                              <1> 	;		     ; AL = AH * 10h + AL
  3280                              <1> 	;mov 	ch, al ; century (BCD)
  3281                              <1> 	;mov 	al, [year]
  3282                              <1> 	; al = year (0-99) ; 01/06/2022
  3283 00003856 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3284 00003858 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3285                              <1> 			     ; AL = AH * 10h + AL
  3286 0000385A 88C1                <1> 	mov 	cl, al ; year (BCD)
  3287 0000385C A0[006A0000]        <1>         mov 	al, [month]
  3288 00003861 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3289 00003863 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3290                              <1> 			     ; AL = AH * 10h + AL
  3291 00003865 88C6                <1> 	mov 	dh, al ; month (BCD)
  3292 00003867 A0[016A0000]        <1> 	mov 	al, [day]
  3293 0000386C D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3294 0000386E D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3295                              <1> 			     ; AL = AH * 10h + AL
  3296                              <1> 	; 01/06/2022 (BugFix)
  3297 00003870 88C2                <1> 	mov 	dl, al ; day (BCD)
  3298                              <1> 
  3299                              <1> 	; Set real-time clock date
  3300 00003872 E879000000          <1> 	call	set_rtc_date
  3301                              <1> set_time:
  3302                              <1>         ; Read real-time clock time 
  3303                              <1> 	; (get day light saving time bit status)
  3304 00003877 FA                  <1>  	cli
  3305 00003878 E8DBD2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3306                              <1> 	; cf = 1 -> al = 0
  3307 0000387D 7207                <1>         jc      short stime1
  3308 0000387F B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3309 00003881 E8BAD2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3310                              <1> stime1:
  3311 00003886 FB                  <1> 	sti
  3312 00003887 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3313 00003889 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3314                              <1> 	; DL = 1 or 0 (day light saving time)
  3315                              <1> 	;	
  3316 0000388B A0[026A0000]        <1> 	mov 	al, [hour]
  3317 00003890 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3318 00003892 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3319                              <1> 			     ; AL = AH * 10h + AL
  3320 00003894 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3321 00003896 A0[036A0000]        <1>         mov     al, [minute]
  3322 0000389B D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3323 0000389D D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3324                              <1> 			     ; AL = AH * 10h + AL
  3325 0000389F 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3326 000038A1 A0[046A0000]        <1>         mov     al, [second]
  3327 000038A6 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3328 000038A8 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3329                              <1> 			     ; AL = AH * 10h + AL
  3330 000038AA 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3331                              <1> 
  3332                              <1> 	; Set real-time clock time
  3333                              <1>  	; call	set_rtc_time
  3334                              <1> set_rtc_time:
  3335                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)		  :
  3336                              <1> 	; 15/03/2015							  :
  3337                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code		  :
  3338                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES		  :
  3339                              <1> 	; INT 1Ah							  :
  3340                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			  :
  3341                              <1> 	;      (CH) = HOURS IN BCD (00-23)			          :
  3342                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			          :
  3343                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			          :
  3344                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.      :
  3345                              <1> 	;								  :
  3346                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3347                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3348                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3349                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3350                              <1> 	;								  :
  3351                              <1> RTC_30: 			; SET RTC TIME
  3352 000038AC FA                  <1> 	cli
  3353 000038AD E8A6D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3354 000038B2 7305                <1> 	JNC	short RTC_35	; GO AROUND IF CLOCK OPERATING
  3355 000038B4 E886000000          <1> 	CALL	RTC_STA 	; ELSE TRY INITIALIZING CLOCK
  3356                              <1> RTC_35:
  3357 000038B9 88F4                <1> 	MOV	AH,DH		; GET TIME BYTE - SECONDS
  3358 000038BB B000                <1> 	MOV	AL,CMOS_SECONDS ; ADDRESS SECONDS
  3359 000038BD E89D000000          <1> 	CALL	CMOS_WRITE	; UPDATE SECONDS
  3360 000038C2 88CC                <1> 	MOV	AH,CL		; GET TIME BYTE - MINUTES
  3361 000038C4 B002                <1> 	MOV	AL,CMOS_MINUTES ; ADDRESS MINUTES
  3362 000038C6 E894000000          <1> 	CALL	CMOS_WRITE	; UPDATE MINUTES
  3363 000038CB 88EC                <1> 	MOV	AH,CH		; GET TIME BYTE - HOURS
  3364 000038CD B004                <1> 	MOV	AL,CMOS_HOURS	; ADDRESS HOURS
  3365 000038CF E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3366                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3367 000038D4 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3368 000038D8 E863D2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT TIME
  3369 000038DD 2462                <1> 	AND	AL,01100010B	; MASK FOR VALID BIT POSITIONS
  3370 000038DF 0C02                <1> 	OR	AL,00000010B	; TURN ON 24 HOUR MODE
  3371 000038E1 80E201              <1> 	AND	DL,00000001B	; USE ONLY THE DSE BIT
  3372 000038E4 08D0                <1> 	OR	AL,DL		; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3373 000038E6 86E0                <1> 	XCHG	AH,AL		; PLACE IN WORK REGISTER AND GET ADDRESS
  3374 000038E8 E872000000          <1> 	CALL	CMOS_WRITE	; SET NEW ALARM BITS
  3375 000038ED F8                  <1> 	CLC			; SET CY= 0
  3376 000038EE FB                  <1> 	sti
  3377 000038EF C3                  <1> 	RETn			; RETURN WITH CY= 0
  3378                              <1> 
  3379                              <1> set_rtc_date:
  3380                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)	   :
  3381                              <1> 	; 15/03/2015						   :
  3382                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	   :
  3383                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	   :
  3384                              <1> 	; INT 1Ah						   :
  3385                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3386                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3387                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3388                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3389                              <1> 	;     (DL) = DAY IN BCD (01-31).			   :
  3390                              <1> 	;							   :
  3391                              <1> RTC_50: 			; SET RTC DATE
  3392 000038F0 FA                  <1> 	cli
  3393 000038F1 E862D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3394 000038F6 7305                <1> 	JNC	short RTC_55	; GO AROUND IF NO ERROR
  3395 000038F8 E842000000          <1> 	CALL	RTC_STA 	; ELSE INITIALIZE CLOCK
  3396                              <1> RTC_55:
  3397 000038FD 66B80600            <1> 	MOV	AX,CMOS_DAY_WEEK ; ADDRESS OF DAY OF WEEK BYTE
  3398 00003901 E859000000          <1> 	CALL	CMOS_WRITE	; LOAD ZEROS TO DAY OF WEEK
  3399 00003906 88D4                <1> 	MOV	AH,DL		; GET DAY OF MONTH BYTE
  3400 00003908 B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH BYTE
  3401 0000390A E850000000          <1> 	CALL	CMOS_WRITE	; WRITE OF DAY OF MONTH REGISTER
  3402 0000390F 88F4                <1> 	MOV	AH,DH		; GET MONTH
  3403 00003911 B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH BYTE
  3404 00003913 E847000000          <1> 	CALL	CMOS_WRITE	; WRITE MONTH REGISTER
  3405 00003918 88CC                <1> 	MOV	AH,CL		; GET YEAR BYTE
  3406 0000391A B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR REGISTER
  3407 0000391C E83E000000          <1> 	CALL	CMOS_WRITE	; WRITE YEAR REGISTER
  3408 00003921 88EC                <1> 	MOV	AH,CH		; GET CENTURY BYTE
  3409 00003923 B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY BYTE
  3410 00003925 E835000000          <1> 	CALL	CMOS_WRITE	; WRITE CENTURY LOCATION
  3411                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3412 0000392A 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3413 0000392E E80DD2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT SETTINGS
  3414 00003933 247F                <1> 	AND	AL,07FH 	; CLEAR 'SET BIT'
  3415 00003935 86E0                <1> 	XCHG	AH,AL		; MOVE TO WORK REGISTER
  3416 00003937 E823000000          <1> 	CALL	CMOS_WRITE	; AND START CLOCK UPDATING
  3417 0000393C F8                  <1> 	CLC			; SET CY= 0
  3418 0000393D FB                  <1> 	sti
  3419 0000393E C3                  <1> 	RETn			; RETURN CY=0
  3420                              <1> 
  3421                              <1> 	; 15/03/2015
  3422                              <1> RTC_STA:			; INITIALIZE REAL TIME CLOCK
  3423 0000393F B426                <1> 	mov	ah, 26h
  3424 00003941 B00A                <1> 	mov	al, CMOS_REG_A	; ADDRESS REGISTER A AND LOAD DATA MASK
  3425 00003943 E817000000          <1> 	CALL	CMOS_WRITE	; INITIALIZE STATUS REGISTER A
  3426 00003948 B482                <1> 	mov	ah, 82h
  3427 0000394A B00B                <1> 	mov 	al, CMOS_REG_B	; SET "SET BIT" FOR CLOCK INITIALIZATION
  3428 0000394C E80E000000          <1> 	CALL	CMOS_WRITE	; AND 24 HOUR MODE TO REGISTER B
  3429 00003951 B00C                <1> 	MOV	AL,CMOS_REG_C	; ADDRESS REGISTER C
  3430 00003953 E8E8D1FFFF          <1> 	CALL	CMOS_READ	; READ REGISTER C TO INITIALIZE
  3431 00003958 B00D                <1> 	MOV	AL,CMOS_REG_D	; ADDRESS REGISTER D
  3432                              <1> 	;CALL	CMOS_READ	; READ REGISTER D TO INITIALIZE
  3433                              <1> 	;RETn
  3434                              <1> 	; 12/02/2022
  3435 0000395A E9E1D1FFFF          <1> 	jmp	CMOS_READ
  3436                              <1> 
  3437                              <1> 	; 15/03/2015
  3438                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3439                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3440 0000395F 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3441                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3442 00003960 D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3443 00003962 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3444 00003963 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3445 00003965 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3446 00003966 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3447 00003968 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3448 0000396A E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3449 0000396C B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3450 0000396E D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3451 00003970 E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3452 00003972 90                  <1> 	nop			; I/O DELAY
  3453 00003973 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3454                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3455 00003975 9D                  <1> 	popf	
  3456 00003976 C3                  <1> 	RETn
  3457                              <1> 
  3458                              <1> bf_init:
  3459                              <1> 	; 14/08/2015
  3460                              <1> 	; 02/07/2015
  3461                              <1> 	; 01/07/2015
  3462                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3463                              <1> 	; Buffer (pointer) initialization !
  3464                              <1> 	; 
  3465                              <1> 	; 17/07/2013 - 24/07/2013
  3466                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3467                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3468                              <1> 	;
  3469 00003977 BF[1C700000]        <1> 	mov	edi, bufp 
  3470 0000397C B8[0C7D0000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3471 00003981 29D2                <1> 	sub	edx, edx
  3472 00003983 FECA                <1> 	dec	dl
  3473 00003985 31C9                <1> 	xor	ecx, ecx
  3474 00003987 49                  <1> 	dec	ecx
  3475                              <1> bi0:
  3476 00003988 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3477 0000398D AB                  <1> 	stosd
  3478 0000398E 89C6                <1> 	mov	esi, eax
  3479 00003990 8916                <1> 	mov	[esi], edx ; 000000FFh
  3480                              <1> 			    ; Not a valid device sign
  3481 00003992 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3482                              <1> 		      ; Not a valid block number sign 	 	
  3483 00003995 3D[DC700000]        <1> 	cmp	eax, buffer
  3484 0000399A 77EC                <1> 	ja	short bi0
  3485 0000399C B8[0C7D0000]        <1> 	mov	eax, sb0
  3486 000039A1 AB                  <1> 	stosd
  3487 000039A2 B8[147F0000]        <1> 	mov	eax, sb1
  3488 000039A7 AB                  <1> 	stosd
  3489 000039A8 89C6                <1> 	mov	esi, eax ; offset sb1
  3490 000039AA 8916                <1> 	mov	[esi], edx ; 000000FFh
  3491                              <1> 			    ; Not a valid device sign
  3492 000039AC 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3493                              <1> 		      ; Not a valid block number sign 	 
  3494                              <1> 	; 14/08/2015
  3495                              <1> 	;call 	rdev_init
  3496                              <1> 	;retn
  3497                              <1> 
  3498                              <1> rdev_init: ; root device, super block buffer initialization
  3499                              <1> 	; 01/02/2022
  3500                              <1> 	; 14/08/2015
  3501                              <1> 	; Retro UNIX 386 v1 feature only !
  3502                              <1> 	;
  3503                              <1> 	; NOTE: Disk partitions (file systems), logical
  3504                              <1> 	; drive initialization, partition's start sector etc.
  3505                              <1> 	; will be coded here, later in 'ldrv_init'	
  3506                              <1> 
  3507 000039AF 0FB605[8A670000]    <1> 	movzx	eax, byte [boot_drv]
  3508                              <1> rdi_0:
  3509 000039B6 3C80                <1> 	cmp	al, 80h
  3510 000039B8 7202                <1> 	jb	short rdi_1
  3511 000039BA 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3512                              <1> rdi_1:
  3513 000039BC A2[42700000]        <1> 	mov	[rdev], al
  3514 000039C1 BB[0C7D0000]        <1>         mov	ebx, sb0 ; super block buffer
  3515 000039C6 8903                <1> 	mov 	[ebx], eax
  3516 000039C8 B001                <1> 	mov	al, 1 ; eax = 1
  3517 000039CA 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3518                              <1> 	;call 	diskio
  3519                              <1> 	;retn
  3520                              <1> 	; 01/02/2022
  3521 000039CD E9C1250000          <1> 	jmp	diskio
  3522                              <1> 
  3523                              <1> ; 23/10/2015
  3524                              <1> com1_irq4:
  3525 000039D2 [DA390000]          <1> 	dd dummy_retn
  3526                              <1> com2_irq3:
  3527 000039D6 [DA390000]          <1> 	dd dummy_retn
  3528                              <1> 
  3529                              <1> dummy_retn:
  3530 000039DA C3                  <1> 	retn
  2048                                  %include 'u1.s'        ; 10/05/2015
  2049                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC
  2050                              <1> ; Last Modification: 27/02/2022
  2051                              <1> ; ----------------------------------------------------------------------------
  2052                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2053                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2054                              <1> ;
  2055                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2056                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2057                              <1> ; <Bell Laboratories (17/3/1972)>
  2058                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2059                              <1> ;
  2060                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2061                              <1> ;
  2062                              <1> ; ****************************************************************************
  2063                              <1> ; 23/11/2015
  2064                              <1> 
  2065                              <1> unkni: ; / used for all system calls
  2066                              <1> sysent: ; < enter to system call >
  2067                              <1> 	; 27/02/2022
  2068                              <1> 	; 01/02/2022
  2069                              <1> 	; 19/10/2015
  2070                              <1> 	; 21/09/2015
  2071                              <1> 	; 01/07/2015
  2072                              <1> 	; 19/05/2015
  2073                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2074                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2075                              <1> 	;
  2076                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2077                              <1> 	; The trap type is determined and an indirect jump is made to 
  2078                              <1> 	; the appropriate system call handler. If there is a trap inside
  2079                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2080                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2081                              <1> 	; instructor is decoded to get the the system code part (see
  2082                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2083                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2084                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2085                              <1> 	; is called. If the call is legitimate control passes to the
  2086                              <1> 	; appropriate system routine.
  2087                              <1> 	;
  2088                              <1> 	; Calling sequence:
  2089                              <1> 	;	Through a trap caused by any sys call outside the system.
  2090                              <1> 	; Arguments:
  2091                              <1> 	;	Arguments of particular system call.	
  2092                              <1> 	; ...............................................................
  2093                              <1> 	;	
  2094                              <1> 	; Retro UNIX 8086 v1 modification: 
  2095                              <1> 	;       System call number is in EAX register.
  2096                              <1> 	;
  2097                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2098                              <1> 	;	registers depending of function details.
  2099                              <1>   	;
  2100                              <1> 	; 16/04/2015
  2101 000039DB 368925[54700000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2102                              <1> 	; save user registers
  2103 000039E2 1E                  <1> 	push	ds
  2104 000039E3 06                  <1> 	push	es
  2105 000039E4 0FA0                <1> 	push	fs
  2106 000039E6 0FA8                <1> 	push	gs
  2107 000039E8 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2108                              <1> 	;
  2109                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2110                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2111                              <1> 	;	for saving/restoring user registers.)
  2112                              <1> 	;
  2113 000039E9 50                  <1> 	push	eax ; 01/07/2015
  2114 000039EA 66B81000            <1> 	mov     ax, KDATA
  2115 000039EE 8ED8                <1>         mov     ds, ax
  2116 000039F0 8EC0                <1>         mov     es, ax
  2117 000039F2 8EE0                <1>         mov     fs, ax
  2118 000039F4 8EE8                <1>         mov     gs, ax
  2119 000039F6 A1[986C0000]        <1> 	mov	eax, [k_page_dir]
  2120 000039FB 0F22D8              <1> 	mov	cr3, eax
  2121 000039FE 58                  <1> 	pop	eax ; 01/07/2015
  2122                              <1> 	; 19/10/2015
  2123 000039FF FC                  <1> 	cld
  2124                              <1> 	;
  2125 00003A00 FE05[53700000]      <1> 	inc	byte [sysflg]
  2126                              <1> 		; incb sysflg / indicate a system routine is in progress
  2127 00003A06 FB                  <1>         sti 	; 18/01/2014
  2128                              <1> 	;jnz	panic ; 24/05/2013
  2129                              <1> 		; beq 1f
  2130                              <1> 		; jmp panic ; / called if trap inside system
  2131                              <1> 	; 01/02/2022
  2132 00003A07 7405                <1> 	jz	short sysent_1
  2133 00003A09 E984F9FFFF          <1> 	jmp	panic
  2134                              <1> sysent_1:
  2135                              <1> ;1:	; 16/04/2015
  2136 00003A0E A3[5C700000]        <1> 	mov	[u.r0], eax
  2137 00003A13 8925[58700000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2138                              <1> 	;
  2139                              <1> 		; mov $s.syst+2,clockp
  2140                              <1> 		; mov r0,-(sp) / save user registers 
  2141                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2142                              <1> 			   ; / in u.r0
  2143                              <1> 		; mov r1,-(sp)
  2144                              <1> 		; mov r2,-(sp)
  2145                              <1> 		; mov r3,-(sp)
  2146                              <1> 		; mov r4,-(sp)
  2147                              <1> 		; mov r5,-(sp)
  2148                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2149                              <1> 		             ; / arithmetic unit
  2150                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2151                              <1> 		             ; / extended arithmetic unit
  2152                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2153                              <1> 		             ; / arithmetic unit
  2154                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2155                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2156                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2157                              <1> 		; sub $sys,r0 / get xxx code
  2158 00003A19 C1E002              <1> 	shl	eax, 2
  2159                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2160 00003A1C 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2161                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2162                              <1> 	;jnb	short badsys
  2163                              <1> 		; bhis badsys / yes, bad system call
  2164                              <1> 	; 27/02/2022
  2165 00003A21 7205                <1> 	jb	short _2
  2166 00003A23 E954010000          <1> 	jmp	badsys
  2167                              <1> _2:
  2168                              <1> 	; 27/02/2022
  2169                              <1> 	;cmc
  2170                              <1> 	;pushf	
  2171                              <1> 	;push	eax
  2172 00003A28 8B2D[54700000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2173                              <1> 	;mov	al, 0FEh ; 11111110b
  2174                              <1> 	;;adc	al, 0 ; al = al + cf
  2175                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2176 00003A2E 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2177                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2178                              <1> 				 ; / and clear carry bit
  2179                              <1> 	;pop	ebp ; eax
  2180 00003A32 89C5                <1> 	mov	ebp, eax
  2181                              <1> 	;popf
  2182                              <1>         ;;jc	badsys
  2183                              <1> 	; 27/02/2022
  2184                              <1> 	;jnc	short _3
  2185                              <1> 	;jmp	badsys
  2186                              <1> ;_3:
  2187 00003A34 A1[5C700000]        <1> 	mov	eax, [u.r0]
  2188                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2189 00003A39 FFA5[3F3A0000]      <1> 	jmp	dword [ebp+syscalls]
  2190                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2191                              <1> 		            ; / to proper system routine.
  2192                              <1> syscalls: ; 1:
  2193                              <1> 	; 21/09/2015
  2194                              <1> 	; 01/07/2015
  2195                              <1> 	; 16/04/2015 (32 bit address modification) 
  2196 00003A3F [463B0000]          <1> 	dd sysrele	; / 0
  2197 00003A43 [EE3B0000]          <1> 	dd sysexit 	; / 1
  2198 00003A47 [193D0000]          <1> 	dd sysfork 	; / 2
  2199 00003A4B [1F3E0000]          <1> 	dd sysread 	; / 3
  2200 00003A4F [323E0000]          <1> 	dd syswrite 	; / 4
  2201 00003A53 [9B3E0000]          <1> 	dd sysopen 	; / 5
  2202 00003A57 [CA3F0000]          <1> 	dd sysclose 	; / 6
  2203 00003A5B [943C0000]          <1> 	dd syswait 	; / 7
  2204 00003A5F [473F0000]          <1> 	dd syscreat 	; / 8
  2205 00003A63 [7C430000]          <1> 	dd syslink 	; / 9
  2206 00003A67 [38440000]          <1> 	dd sysunlink 	; / 10
  2207 00003A6B [FF440000]          <1> 	dd sysexec 	; / 11
  2208 00003A6F [884B0000]          <1> 	dd syschdir 	; / 12
  2209 00003A73 [6D4C0000]          <1> 	dd systime 	; / 13
  2210 00003A77 [833F0000]          <1> 	dd sysmkdir 	; / 14
  2211 00003A7B [DA4B0000]          <1> 	dd syschmod 	; / 15
  2212 00003A7F [3D4C0000]          <1> 	dd syschown 	; / 16
  2213 00003A83 [A04C0000]          <1> 	dd sysbreak 	; / 17
  2214 00003A87 [C0480000]          <1> 	dd sysstat 	; / 18
  2215 00003A8B [704D0000]          <1> 	dd sysseek 	; / 19
  2216 00003A8F [824D0000]          <1> 	dd systell 	; / 20
  2217 00003A93 [B6580000]          <1> 	dd sysmount 	; / 21
  2218 00003A97 [A1590000]          <1> 	dd sysumount 	; / 22
  2219 00003A9B [FE4D0000]          <1> 	dd syssetuid 	; / 23
  2220 00003A9F [2F4E0000]          <1> 	dd sysgetuid 	; / 24
  2221 00003AA3 [7C4C0000]          <1> 	dd sysstime 	; / 25
  2222 00003AA7 [F24D0000]          <1> 	dd sysquit 	; / 26
  2223 00003AAB [E64D0000]          <1> 	dd sysintr 	; / 27
  2224 00003AAF [9D480000]          <1> 	dd sysfstat 	; / 28
  2225 00003AB3 [E23F0000]          <1> 	dd sysemt 	; / 29
  2226 00003AB7 [2A400000]          <1> 	dd sysmdate 	; / 30
  2227 00003ABB [84400000]          <1> 	dd sysstty 	; / 31
  2228 00003ABF [6F420000]          <1> 	dd sysgtty 	; / 32
  2229 00003AC3 [25400000]          <1> 	dd sysilgins 	; / 33
  2230 00003AC7 [4C620000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2231                              <1> 			     ; 11/06/2014
  2232 00003ACB [63620000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2233                              <1> 			     ; 01/07/2015
  2234 00003ACF [3B630000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2235                              <1> 			     ; 21/09/2015 - get last error number
  2236                              <1> end_of_syscalls:
  2237                              <1> 
  2238                              <1> error:
  2239                              <1> 	; 17/09/2015
  2240                              <1> 	; 03/09/2015
  2241                              <1> 	; 01/09/2015
  2242                              <1> 	; 09/06/2015
  2243                              <1> 	; 13/05/2015
  2244                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2245                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2246                              <1> 	;
  2247                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2248                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2249                              <1> 	;
  2250                              <1> 	; INPUTS -> none
  2251                              <1> 	; OUTPUTS ->
  2252                              <1> 	;	processor status - carry (c) bit is set (means error)
  2253                              <1> 	;
  2254                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2255                              <1> 	; 	      Because, jumps to error procedure
  2256                              <1> 	;	      disrupts push-pop nesting balance)
  2257                              <1> 	;
  2258 00003AD3 8B2D[54700000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2259 00003AD9 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2260                              <1> 				 ; (system call will return with cf = 1)
  2261                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2262                              <1> 		               ; / users stack
  2263                              <1> 	; 17/09/2015
  2264 00003ADD 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2265                              <1> 				 ; for saving/restoring user registers	
  2266                              <1> 	;cmp	ebp, [u.usp]
  2267                              <1> 	;je	short err0	
  2268 00003AE0 892D[58700000]      <1> 	mov	[u.usp], ebp
  2269                              <1> ;err0:
  2270                              <1> 	; 01/09/2015
  2271 00003AE6 8B25[58700000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2272                              <1> 				    ; 10/04/2013
  2273                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2274                              <1> 				    ; related procedures will jump to 'error'
  2275                              <1> 				    ; procedure directly without returning to 
  2276                              <1> 				    ; the caller procedure. So, stack pointer
  2277                              <1>                                     ; must be restored here.)
  2278                              <1> 	; 13/05/2015
  2279                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2280                              <1> 	;	'get last error' system call later. 	
  2281                              <1> 
  2282                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2283 00003AEC C605[BD700000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2284                              <1> 
  2285                              <1> sysret: ; < return from system call>
  2286                              <1> 	; 01/02/2022
  2287                              <1> 	; 10/09/2015
  2288                              <1> 	; 29/07/2015
  2289                              <1> 	; 25/06/2015
  2290                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2291                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2292                              <1> 	;
  2293                              <1> 	; 'sysret' first checks to see if process is about to be 
  2294                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2295                              <1> 	; If not, following happens:	 
  2296                              <1> 	; 	1) The user's stack pointer is restored.
  2297                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2298                              <1> 	;	   i-node has been modified. If it has, it is written out
  2299                              <1> 	;	   via 'ppoke'.
  2300                              <1> 	;	3) If the super block has been modified, it is written out
  2301                              <1> 	;	   via 'ppoke'.				
  2302                              <1> 	;	4) If the dismountable file system's super block has been
  2303                              <1> 	;	   modified, it is written out to the specified device
  2304                              <1> 	;	   via 'ppoke'.
  2305                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2306                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2307                              <1> 	;	   another user a chance to run.
  2308                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2309                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2310                              <1> 	;
  2311                              <1> 	; Calling sequence:
  2312                              <1> 	;	jump table or 'br sysret'
  2313                              <1> 	; Arguments: 
  2314                              <1> 	;	-	
  2315                              <1> 	; ...............................................................
  2316                              <1> 	;	
  2317                              <1> 	; ((AX=r1 for 'iget' input))
  2318                              <1> 	;	
  2319                              <1> 	;xor	ax, ax ; 04/05/2013
  2320                              <1> 	; 01/02/2022
  2321 00003AF3 31C0                <1> 	xor	eax, eax
  2322                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2323 00003AF5 FEC0                <1> 	inc	al ; 04/05/2013
  2324 00003AF7 3805[A4700000]      <1> 	cmp	[u.bsys], al ; 1
  2325                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2326                              <1>         ;jnb	sysexit ; 04/05/2013
  2327                              <1> 		; bne sysexit / of an error? yes, go to sysexit
  2328                              <1> 	; 01/02/2022
  2329 00003AFD 7205                <1> 	jb	short sysret_2
  2330 00003AFF E9EA000000          <1> 	jmp	sysexit
  2331                              <1> sysret_2:
  2332                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2333                              <1> 		; mov u.sp,sp / no point stack to users stack
  2334 00003B04 FEC8                <1> 	dec 	al ; mov ax, 0
  2335                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2336 00003B06 E8DE160000          <1> 	call	iget
  2337                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2338                              <1> 		            ; / it is written out
  2339 00003B0B 6631C0              <1> 	xor 	ax, ax ; 0
  2340 00003B0E 3805[51700000]      <1> 	cmp	[smod], al ; 0
  2341                              <1> 		; tstb	smod / has the super block been modified
  2342 00003B14 7614                <1> 	jna	short sysret1
  2343                              <1> 		; beq	1f / no, 1f
  2344 00003B16 A2[51700000]        <1> 	mov	[smod], al ; 0
  2345                              <1> 		; clrb smod / yes, clear smod
  2346 00003B1B BB[0C7D0000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2347 00003B20 66810B0002          <1>    	or	word [ebx], 200h ;;
  2348                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2349                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2350                              <1> 		      	      ; / output
  2351                              <1> 	; AX = 0
  2352 00003B25 E851230000          <1> 	call 	poke ; 07/08/2013
  2353                              <1> 	;call	ppoke
  2354                              <1> 	; AX = 0
  2355                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2356                              <1> sysret1: ;1:
  2357 00003B2A 3805[52700000]      <1> 	cmp	[mmod], al ; 0
  2358                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2359                              <1> 		           ; / system
  2360 00003B30 7614                <1> 	jna	short sysrel0
  2361                              <1> 		; beq 1f / been modified?  no, 1f
  2362 00003B32 A2[52700000]        <1> 	mov	[mmod], al ; 0	
  2363                              <1> 		; clrb	mmod / yes, clear mmod
  2364                              <1>         ;mov    ax, [mntd]
  2365                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2366 00003B37 BB[147F0000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2367                              <1>         ;;mov	[ebx], al
  2368                              <1> 	;mov    [sb1], al
  2369                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2370 00003B3C 66810B0002          <1> 	or	word [ebx], 200h
  2371                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2372                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2373 00003B41 E835230000          <1> 	call	poke ; 07/08/2013
  2374                              <1> 	;call	ppoke 
  2375                              <1> 		; jsr r0,ppoke / write it out to its device
  2376                              <1>         ;xor    al, al ; 26/04/2013       
  2377                              <1> ;1:
  2378                              <1> 		; tstb uquant / is the time quantum 0?
  2379                              <1> 		; bne 1f / no, don't swap it out
  2380                              <1> 
  2381                              <1> sysrele: ; < release >
  2382                              <1> 	; 14/10/2015
  2383                              <1> 	; 01/09/2015
  2384                              <1> 	; 24/07/2015
  2385                              <1> 	; 14/05/2015
  2386                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2387                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2388                              <1> 	;
  2389                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2390                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2391                              <1> 	; turns off the system flag. It then checked to see if there is
  2392                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2393                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2394                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2395                              <1> 	; the user, a rti is made.
  2396                              <1> 	;
  2397                              <1> 	; Calling sequence:
  2398                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2399                              <1> 	; Arguments:
  2400                              <1> 	;	-	
  2401                              <1> 	; ...............................................................
  2402                              <1> 	;	
  2403                              <1> 	; 23/02/2014 (swapret)
  2404                              <1> 	; 22/09/2013
  2405                              <1> sysrel0: ;1:
  2406 00003B46 803D[98700000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2407                              <1> 		; tstb uquant / is the time quantum 0?
  2408 00003B4D 7705                <1>         ja      short swapret
  2409                              <1> 		; bne 1f / no, don't swap it out
  2410                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2411 00003B4F E82B130000          <1> 	call	tswap
  2412                              <1> 		; jsr r0,tswap / yes, swap it out
  2413                              <1> ;
  2414                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2415                              <1> swapret: ;1:
  2416                              <1> 	; 10/09/2015
  2417                              <1> 	; 01/09/2015
  2418                              <1> 	; 14/05/2015
  2419                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2420                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2421                              <1> 	; cli
  2422                              <1> 	; 24/07/2015
  2423                              <1> 	;
  2424                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2425                              <1> 	;; mov	esp, [u.usp]
  2426                              <1> 
  2427                              <1> 	; 22/09/2013
  2428 00003B54 E8FD140000          <1> 	call	isintr
  2429                              <1> 	; 20/10/2013
  2430 00003B59 7405                <1> 	jz	short sysrel1
  2431 00003B5B E877000000          <1> 	call	intract
  2432                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2433                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2434                              <1> 		               ; / action
  2435                              <1> sysrel1:
  2436 00003B60 FA                  <1> 	cli ; 14/10/2015
  2437 00003B61 FE0D[53700000]      <1> 	dec	byte [sysflg]
  2438                              <1> 		; decb sysflg / turn system flag off
  2439 00003B67 A1[AF700000]        <1> 	mov     eax, [u.pgdir]
  2440 00003B6C 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2441                              <1> 			  ; (others are different than kernel page tables) 
  2442                              <1> 	; 10/09/2015
  2443 00003B6F 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2444                              <1> 		; mov (sp)+,sc / restore user registers
  2445                              <1> 		; mov (sp)+,mq
  2446                              <1> 		; mov (sp)+,ac
  2447                              <1> 		; mov (sp)+,r5
  2448                              <1> 		; mov (sp)+,r4
  2449                              <1> 		; mov (sp)+,r3
  2450                              <1> 		; mov (sp)+,r2
  2451                              <1> 	;
  2452 00003B70 A1[5C700000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2453 00003B75 0FA9                <1> 	pop	gs
  2454 00003B77 0FA1                <1> 	pop	fs
  2455 00003B79 07                  <1> 	pop	es
  2456 00003B7A 1F                  <1> 	pop	ds
  2457 00003B7B CF                  <1> 	iretd	
  2458                              <1> 		; rti / no, return from interrupt
  2459                              <1> 
  2460                              <1> badsys:
  2461                              <1> 	; 27/02/2022
  2462                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2463                              <1> 	; (Major Modification: 'core' dumping procedure in
  2464                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2465                              <1> 	;	has been changed to print 'Invalid System Call !'
  2466                              <1> 	;	message on the user's console tty.)
  2467                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2468                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2469                              <1> 	; (EAX = Function number)  
  2470                              <1> 	;
  2471 00003B7C FE05[A4700000]      <1> 	inc	byte [u.bsys]
  2472                              <1> 	;
  2473 00003B82 8B1D[54700000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2474 00003B88 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2475 00003B8A E879DBFFFF          <1> 	call	dwordtohex
  2476 00003B8F 8915[F2690000]      <1> 	mov	[bsys_msg_eip], edx
  2477 00003B95 A3[F6690000]        <1> 	mov	[bsys_msg_eip+4], eax
  2478 00003B9A A1[5C700000]        <1> 	mov	eax, [u.r0]
  2479 00003B9F E864DBFFFF          <1> 	call	dwordtohex
  2480 00003BA4 8915[E2690000]      <1> 	mov	[bsys_msg_eax], edx
  2481 00003BAA A3[E6690000]        <1> 	mov	[bsys_msg_eax+4], eax
  2482                              <1> 	; 27/02/2022
  2483                              <1> 	;xor	eax, eax
  2484                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2485                              <1> 	;mov	ebx, [u.fofp]
  2486                              <1> 	;mov	[ebx], eax
  2487                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2488                              <1> 	;inc	eax
  2489                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2490                              <1> 		; writei
  2491                              <1> 		; INPUTS ->
  2492                              <1> 		;    r1 - inode number
  2493                              <1> 		;    u.count - byte count to be written
  2494                              <1> 		;    u.base - points to user buffer
  2495                              <1> 		;    u.fofp - points to word with current file offset
  2496                              <1> 		; OUTPUTS ->
  2497                              <1> 		;    u.count - cleared
  2498                              <1> 		;    u.nread - accumulates total bytes passed back	
  2499                              <1> 		;
  2500                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2501                              <1> 	;call	writei
  2502                              <1> 	;;mov	eax, 1
  2503                              <1> 	;jmp	sysexit
  2504                              <1> 
  2505                              <1> 	; 27/02/2022
  2506 00003BAF BE[C3690000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2507 00003BB4 0FB61D[A5700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2508 00003BBB 8A83[B76D0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2509 00003BC1 C605[C76C0000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2510 00003BC8 A2[AA700000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2511 00003BCD E84E270000          <1> 	call	print_cmsg
  2512                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2513 00003BD2 E9FCFEFFFF          <1> 	jmp	error
  2514                              <1> 
  2515                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2516                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2517                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2518                              <1> 		; br 1f / error
  2519                              <1> 		; neg r1 / negate the i-number to open the core image file
  2520                              <1> 		       ; / for writing
  2521                              <1> 		; jsr r0,iopen / open the core image file
  2522                              <1> 		; jsr r0,itrunc / free all associated blocks
  2523                              <1> 		; br 2f
  2524                              <1> ;1:
  2525                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2526                              <1> 		; jsr r0,maknod / make an i-node
  2527                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2528                              <1> ;2:
  2529                              <1> 		; mov $core,u.base / move address core to u.base
  2530                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2531                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2532                              <1> 		; clr u.off / clear user offset
  2533                              <1> 		; jsr r0,writei / write out the core image to the user
  2534                              <1> 		; mov $user,u.base / pt. u.base to user
  2535                              <1> 		; mov $64.,u.count / u.count = 64
  2536                              <1> 		; jsr r0,writei / write out all the user parameters
  2537                              <1> 		; neg r1 / make i-number positive
  2538                              <1> 		; jsr r0,iclose / close the core image file
  2539                              <1> 		; br sysexit /
  2540                              <1> ;3:
  2541                              <1> 		; <core\0\0>
  2542                              <1> 
  2543                              <1> intract: ; / interrupt action
  2544                              <1> 	; 14/10/2015
  2545                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2546                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2547                              <1> 	;
  2548                              <1> 	; Retro UNIX 8086 v1 modification !
  2549                              <1> 	; (Process/task switching and quit routine by using
  2550                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2551                              <1> 	;
  2552                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2553                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2554                              <1> 	;		'intract' will jump to 'sysexit'.
  2555                              <1> 	;	    Intract will return to the caller 
  2556                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2557                              <1> 	; 14/10/2015
  2558 00003BD7 FB                  <1> 	sti
  2559                              <1> 	; 07/12/2013	
  2560 00003BD8 66FF05[9C700000]    <1> 	inc 	word [u.quit]
  2561 00003BDF 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2562 00003BE1 66FF0D[9C700000]    <1> 	dec	word [u.quit]
  2563                              <1> 	; 16/04/2015
  2564 00003BE8 C3                  <1> 	retn
  2565                              <1> intrct0:	
  2566 00003BE9 58                  <1> 	pop	eax ; call intract -> retn
  2567                              <1> 	;
  2568 00003BEA 31C0                <1> 	xor 	eax, eax
  2569 00003BEC FEC0                <1> 	inc	al  ; mov ax, 1
  2570                              <1> ;;;
  2571                              <1> 	; UNIX v1 original 'intract' routine... 
  2572                              <1> 	; / interrupt action
  2573                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2574                              <1> 		; bne 1f / no, 1f
  2575                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2576                              <1> 	; 1: / now in user area
  2577                              <1> 		; mov r1,-(sp) / save r1
  2578                              <1> 		; mov u.ttyp,r1 
  2579                              <1> 			; / pointer to tty buffer in control-to r1
  2580                              <1> 		; cmpb 6(r1),$177
  2581                              <1> 			; / is the interrupt char equal to "del"
  2582                              <1> 		; beq 1f / yes, 1f
  2583                              <1> 		; clrb 6(r1) 
  2584                              <1> 		        ; / no, clear the byte 
  2585                              <1> 			; / (must be a quit character)
  2586                              <1> 		; mov (sp)+,r1 / restore r1
  2587                              <1> 		; clr u.quit / clear quit flag
  2588                              <1> 		; bis $20,2(sp) 
  2589                              <1> 		    	; / set trace for quit (sets t bit of 
  2590                              <1> 			; / ps-trace trap)
  2591                              <1> 		; rti   ;  / return from interrupt
  2592                              <1> 	; 1: / interrupt char = del
  2593                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2594                              <1> 			   ; / in the buffer
  2595                              <1> 		; mov (sp)+,r1 / restore r1
  2596                              <1> 		; cmp u.intr,$core / should control be 
  2597                              <1> 				; / transferred to loc core?
  2598                              <1> 		; blo 1f
  2599                              <1> 		; jmp *u.intr / user to do rti yes, 
  2600                              <1> 				; / transfer to loc core
  2601                              <1> 	; 1:
  2602                              <1> 		; sys 1 / exit
  2603                              <1> 
  2604                              <1> sysexit: ; <terminate process>
  2605                              <1> 	; 01/02/2022
  2606                              <1> 	; 01/09/2015
  2607                              <1> 	; 31/08/2015
  2608                              <1> 	; 14/05/2015
  2609                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2610                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2611                              <1> 	;
  2612                              <1> 	; 'sysexit' terminates a process. First each file that
  2613                              <1> 	; the process has opened is closed by 'flose'. The process
  2614                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2615                              <1> 	; searched to find children of the dying process. If any of
  2616                              <1> 	; children are zombies (died by not waited for), they are
  2617                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2618                              <1> 	; dying process's parent. When the parent is found, it is
  2619                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2620                              <1> 	; one of these, the dying process just dies. If it is waiting
  2621                              <1> 	; for a child process to die, it notified that it doesn't 
  2622                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2623                              <1> 	; (waiting to active). It is awakened and put on runq by
  2624                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2625                              <1> 	; it will never be run again but stays around until a 'wait'
  2626                              <1> 	; is completed by it's parent process. If the parent is not
  2627                              <1> 	; found, process just dies. This means 'swap' is called with
  2628                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2629                              <1> 	; to write out the process and 'rswap' reads the new process
  2630                              <1> 	; over the one that dies..i.e., the dying process is 
  2631                              <1> 	; overwritten and destroyed.	
  2632                              <1>  	;
  2633                              <1> 	; Calling sequence:
  2634                              <1> 	;	sysexit or conditional branch.
  2635                              <1> 	; Arguments:
  2636                              <1> 	;	-	
  2637                              <1> 	; ...............................................................
  2638                              <1> 	;	
  2639                              <1> 	; Retro UNIX 8086 v1 modification: 
  2640                              <1> 	;       System call number (=1) is in EAX register.
  2641                              <1> 	;
  2642                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2643                              <1> 	;       registers depending of function details.
  2644                              <1> 	;
  2645                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2646                              <1> 	;
  2647                              <1> ; / terminate process
  2648                              <1> 	; AX = 1
  2649                              <1> 	;dec 	ax ; 0
  2650                              <1> 	; 01/02/2022
  2651 00003BEE 48                  <1> 	dec	eax ; 0
  2652 00003BEF 66A3[9A700000]      <1> 	mov	[u.intr], ax ; 0
  2653                              <1> 		; clr u.intr / clear interrupt control word
  2654                              <1> 		; clr r1 / clear r1
  2655                              <1> 	; AX = 0
  2656                              <1> sysexit_1: ; 1:
  2657                              <1> 	; AX = File descriptor
  2658                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2659                              <1> 		; / Search the whole list
  2660 00003BF5 E8640D0000          <1> 	call	fclose
  2661                              <1> 		; jsr r0,fclose / close all files the process opened
  2662                              <1> 	;; ignore error return
  2663                              <1> 		; br .+2 / ignore error return
  2664                              <1> 	;inc	ax
  2665 00003BFA FEC0                <1> 	inc	al
  2666                              <1> 		; inc r1 / increment file descriptor
  2667                              <1> 	;cmp	ax, 10
  2668 00003BFC 3C0A                <1> 	cmp	al, 10
  2669                              <1> 		; cmp r1,$10. / end of u.fp list?
  2670 00003BFE 72F5                <1> 	jb	short sysexit_1
  2671                              <1> 		; blt 1b / no, go back
  2672 00003C00 0FB61D[A5700000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2673                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2674 00003C07 88A3[D76D0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2675                              <1> 		; clrb p.stat-1(r1) / free the process
  2676                              <1> 	;shl	bx, 1
  2677 00003C0D D0E3                <1> 	shl	bl, 1
  2678                              <1> 		; asl r1 / use r1 for index into the below tables
  2679 00003C0F 668B8B[766D0000]    <1> 	mov	cx, [ebx+p.pid-2]
  2680                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2681 00003C16 668B93[966D0000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2682                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2683                              <1> 	;xor 	bx, bx ; 0
  2684 00003C1D 30DB                <1> 	xor	bl, bl ; 0
  2685                              <1> 		; clr r2
  2686 00003C1F 31F6                <1> 	xor	esi, esi ; 0
  2687                              <1> 		; clr r5 / initialize reg
  2688                              <1> sysexit_2: ; 1:
  2689                              <1> 	        ; / find children of this dying process, 
  2690                              <1> 		; / if they are zombies, free them
  2691                              <1> 	;add	bx, 2
  2692 00003C21 80C302              <1> 	add	bl, 2
  2693                              <1> 		; add $2,r2 / search parent process table 
  2694                              <1> 		          ; / for dying process's name
  2695 00003C24 66398B[966D0000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2696                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2697 00003C2B 7513                <1> 	jne	short sysexit_4
  2698                              <1> 		; bne 3f / no
  2699                              <1> 	;shr	bx, 1
  2700 00003C2D D0EB                <1> 	shr	bl, 1
  2701                              <1> 		; asr r2 / yes, it is a parent
  2702 00003C2F 80BB[D76D0000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2703                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2704                              <1> 				     ; / dying process a zombie
  2705 00003C36 7506                <1> 	jne	short sysexit_3 
  2706                              <1> 		; bne 2f / no
  2707 00003C38 88A3[D76D0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2708                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2709                              <1> sysexit_3: ; 2:
  2710                              <1> 	;shr	bx, 1
  2711 00003C3E D0E3                <1> 	shl	bl, 1
  2712                              <1> 		; asl r2
  2713                              <1> sysexit_4: ; 3:
  2714                              <1> 		; / search the process name table 
  2715                              <1> 		; / for the dying process's parent
  2716 00003C40 663993[766D0000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2717                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2718 00003C47 7502                <1> 	jne	short sysexit_5
  2719                              <1> 		; bne 3f / no
  2720 00003C49 89DE                <1> 	mov	esi, ebx
  2721                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2722                              <1> 		          ; / process # x2) in r5
  2723                              <1> sysexit_5: ; 3:
  2724                              <1> 	;cmp	bx, nproc + nproc
  2725 00003C4B 80FB20              <1> 	cmp	bl, nproc + nproc
  2726                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2727 00003C4E 72D1                <1> 	jb	short sysexit_2
  2728                              <1> 		; blt 1b / no, go back
  2729                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2730 00003C50 21F6                <1> 	and	esi, esi ; r5=r1
  2731 00003C52 7431                <1> 	jz	short sysexit_6
  2732                              <1> 		; beq 2f / no parent has been found. 
  2733                              <1> 		       ; / The process just dies
  2734 00003C54 66D1EE              <1> 	shr	si, 1
  2735                              <1> 		; asr r1 / set up index to p.stat
  2736 00003C57 8A86[D76D0000]      <1> 	mov	al, [esi+p.stat-1]
  2737                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2738 00003C5D 20C0                <1> 	and	al, al
  2739 00003C5F 7424                <1> 	jz	short sysexit_6
  2740                              <1> 		; beq 2f / if its been freed, 2f
  2741 00003C61 3C03                <1> 	cmp	al, 3
  2742                              <1> 		; cmp r2,$3 / is parent a zombie?
  2743 00003C63 7420                <1> 	je	short sysexit_6
  2744                              <1> 		; beq 2f / yes, 2f
  2745                              <1> 	; BH = 0
  2746 00003C65 8A1D[A5700000]      <1> 	mov	bl, [u.uno]
  2747                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2748 00003C6B C683[D76D0000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2749                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2750                              <1> 	; 05/02/2014
  2751 00003C72 3C01                <1> 	cmp	al, 1 ; SRUN
  2752 00003C74 740F                <1> 	je	short sysexit_6
  2753                              <1> 	;cmp	al, 2
  2754                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2755                              <1> 			  ; / this child to die
  2756                              <1> 	;jne	short sysexit_6	
  2757                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2758                              <1> 	; 05/02/2014
  2759                              <1> 	; p.stat = 2 --> waiting
  2760                              <1> 	; p.stat = 4 --> sleeping
  2761 00003C76 C686[D76D0000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2762                              <1> 	;dec	byte [esi+p.stat-1]
  2763                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2764 00003C7D 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2765                              <1> 	; 
  2766                              <1> 	;mov	ebx, runq + 4
  2767                              <1> 		; mov $runq+4,r2 / on the runq
  2768 00003C80 E8D1120000          <1> 	call	putlu
  2769                              <1> 		; jsr r0, putlu
  2770                              <1> sysexit_6: ; 2:
  2771                              <1> 	; 31/08/2015
  2772                              <1> 		; / the process dies
  2773 00003C85 C605[A5700000]00    <1> 	mov	byte [u.uno], 0
  2774                              <1> 		; clrb u.uno / put zero as the process number, 
  2775                              <1> 	           ; / so "swap" will
  2776 00003C8C E8F8110000          <1> 	call	swap
  2777                              <1> 		; jsr r0,swap / overwrite process with another process
  2778                              <1> hlt_sys:
  2779                              <1> 	;sti ; 18/01/2014
  2780                              <1> hlts0:
  2781 00003C91 F4                  <1> 	hlt
  2782 00003C92 EBFD                <1> 	jmp	short hlts0
  2783                              <1> 		; 0 / and thereby kill it; halt?
  2784                              <1> 
  2785                              <1> 
  2786                              <1> syswait: ; < wait for a processs to die >
  2787                              <1> 	; 12/02/2022
  2788                              <1> 	; 01/02/2022
  2789                              <1> 	; 17/09/2015
  2790                              <1> 	; 02/09/2015
  2791                              <1> 	; 01/09/2015
  2792                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2793                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2794                              <1> 	;
  2795                              <1> 	; 'syswait' waits for a process die. 
  2796                              <1> 	; It works in following way:
  2797                              <1> 	;    1) From the parent process number, the parent's 
  2798                              <1> 	; 	process name is found. The p.ppid table of parent
  2799                              <1> 	;	names is then searched for this process name.
  2800                              <1> 	;	If a match occurs, r2 contains child's process
  2801                              <1> 	;	number. The child status is checked to see if it is
  2802                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2803                              <1> 	;	If it is, the child process is freed and it's name
  2804                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2805                              <1> 	;	If the child is not a zombie, nothing happens and
  2806                              <1> 	;	the search goes on through the p.ppid table until
  2807                              <1> 	;	all processes are checked or a zombie is found.
  2808                              <1> 	;    2) If no zombies are found, a check is made to see if
  2809                              <1> 	;	there are any children at all. If there are none,
  2810                              <1> 	;	an error return is made. If there are, the parent's
  2811                              <1> 	;	status is set to 2 (waiting for child to die),
  2812                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2813                              <1> 	;	is made to wait on the next process.
  2814                              <1> 	;
  2815                              <1> 	; Calling sequence:
  2816                              <1> 	;	?
  2817                              <1> 	; Arguments:
  2818                              <1> 	;	-
  2819                              <1> 	; Inputs: - 
  2820                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2821                              <1> 	; ...............................................................
  2822                              <1> 	;				
  2823                              <1> 	
  2824                              <1> ; / wait for a process to die
  2825                              <1> 
  2826                              <1> syswait_0:
  2827 00003C94 0FB61D[A5700000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2828                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2829 00003C9B D0E3                <1> 	shl	bl, 1
  2830                              <1> 	;shl	bx, 1
  2831                              <1> 		; asl r1 / x2 to get index into p.pid table
  2832 00003C9D 668B83[766D0000]    <1> 	mov	ax, [ebx+p.pid-2]
  2833                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2834 00003CA4 31F6                <1> 	xor	esi, esi
  2835                              <1> 		; clr r2
  2836 00003CA6 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2837                              <1> 	;xor 	cl, cl
  2838                              <1> 		; clr r3 / initialize reg 3
  2839                              <1> syswait_1: ; 1:
  2840                              <1> 	; 12/02/2022
  2841 00003CA8 46                  <1> 	inc	esi
  2842 00003CA9 46                  <1> 	inc	esi
  2843                              <1> 	;add	si, 2
  2844                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2845                              <1> 			  ; / search table of parent processes 
  2846                              <1> 			  ; / for this process name
  2847 00003CAA 663B86[966D0000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2848                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2849                              <1> 			            ; / process number
  2850 00003CB1 7531                <1> 	jne	short syswait_3
  2851                              <1> 		; bne 3f / branch if no match of parent process name
  2852                              <1> 	;inc	cx
  2853 00003CB3 FEC1                <1> 	inc	cl
  2854                              <1> 		; inc r3 / yes, a match, r3 indicates number of children
  2855                              <1> 	; 12/02/2022
  2856 00003CB5 D1EE                <1> 	shr	esi, 1
  2857                              <1> 	;shr	si, 1
  2858                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2859                              <1> 	; The possible states ('p.stat' values) of a process are:
  2860                              <1> 	;	0 = free or unused
  2861                              <1> 	;	1 = active
  2862                              <1> 	;	2 = waiting for a child process to die
  2863                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2864 00003CB7 80BE[D76D0000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2865                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2866 00003CBE 7522                <1> 	jne	short syswait_2
  2867                              <1> 		; bne 2f / no, skip it
  2868 00003CC0 88BE[D76D0000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2869                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2870                              <1> 	; 12/02/2022
  2871 00003CC6 D1E6                <1> 	shl	esi, 1
  2872                              <1> 	;shl	si, 1
  2873                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2874 00003CC8 0FB786[766D0000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2875 00003CCF A3[5C700000]        <1> 	mov	[u.r0], eax
  2876                              <1> 		; mov p.pid-2(r2),*u.r0 
  2877                              <1> 			      ; / put childs process name in (u.r0)
  2878                              <1> 	;
  2879                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2880                              <1> 	;
  2881                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2882                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2883                              <1> 	; system call loop from the application/program if it calls
  2884                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2885                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2886                              <1> 	;
  2887                              <1> 	; Note: syswait will return with error if there is not a
  2888                              <1> 	;       zombie or running process to wait.	
  2889                              <1> 	;
  2890                              <1> 	;sub	ax, ax
  2891                              <1> 	; 01/02/2022
  2892 00003CD4 29C0                <1> 	sub	eax, eax
  2893 00003CD6 668986[966D0000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2894 00003CDD E913FEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2895                              <1> 	;
  2896                              <1> 	;jmp	sysret
  2897                              <1> 		; br sysret1 / return cause child is dead
  2898                              <1> syswait_2: ; 2:
  2899                              <1> 	; 12/02/2022
  2900 00003CE2 D1E6                <1> 	shl	esi, 1
  2901                              <1> 	;shl	si, 1
  2902                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2903                              <1> syswait_3: ; 3:
  2904 00003CE4 6683FE20            <1> 	cmp	si, nproc+nproc
  2905                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2906 00003CE8 72BE                <1> 	jb	short syswait_1
  2907                              <1> 		; blt 1b / no, continue search
  2908                              <1> 	;and	cx, cx
  2909 00003CEA 20C9                <1> 	and	cl, cl
  2910                              <1> 		; tst r3 / one gets here if there are no children 
  2911                              <1> 		       ; / or children that are still active
  2912                              <1> 	; 30/10/2013
  2913 00003CEC 7515                <1> 	jnz	short syswait_4
  2914                              <1> 	;jz	error
  2915                              <1> 		; beq error1 / there are no children, error
  2916 00003CEE 890D[5C700000]      <1> 	mov	[u.r0], ecx ; 0
  2917                              <1> 	; 12/02/2022
  2918 00003CF4 C705[AB700000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2918 00003CFC 0000                <1>
  2919                              <1> 			; miscellaneous/other errors
  2920 00003CFE E9D0FDFFFF          <1> 	jmp	error
  2921                              <1> syswait_4:
  2922 00003D03 8A1D[A5700000]      <1> 	mov	bl, [u.uno]
  2923                              <1> 		; movb u.uno,r1 / there are children so put 
  2924                              <1> 			      ; / parent process number in r1
  2925 00003D09 FE83[D76D0000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2926                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2927                              <1> 				  ; / other children to die
  2928                              <1> 	; 04/11/2013
  2929 00003D0F E875110000          <1> 	call	swap
  2930                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2931 00003D14 E97BFFFFFF          <1> 	jmp	syswait_0
  2932                              <1> 		; br syswait / wait on next process
  2933                              <1> 
  2934                              <1> sysfork: ; < create a new process >
  2935                              <1> 	; 26/02/2022
  2936                              <1> 	; 25/02/2022
  2937                              <1> 	; 01/02/2022
  2938                              <1> 	; 18/09/2015
  2939                              <1> 	; 04/09/2015
  2940                              <1> 	; 02/09/2015
  2941                              <1> 	; 01/09/2015
  2942                              <1> 	; 28/08/2015
  2943                              <1> 	; 14/05/2015
  2944                              <1> 	; 10/05/2015
  2945                              <1> 	; 09/05/2015
  2946                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  2947                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2948                              <1> 	;
  2949                              <1> 	; 'sysfork' creates a new process. This process is referred
  2950                              <1> 	; to as the child process. This new process core image is
  2951                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  2952                              <1> 	; distinction is the return location and the fact that (u.r0)
  2953                              <1> 	; in the old process (parent) contains the process id (p.pid)
  2954                              <1> 	; of the new process (child). This id is used by 'syswait'.
  2955                              <1> 	; 'sysfork' works in the following manner: 	
  2956                              <1> 	;    1) The process status table (p.stat) is searched to find
  2957                              <1> 	;	a process number that is unused. If none are found
  2958                              <1> 	;	an error occurs.
  2959                              <1> 	;    2) when one is found, it becomes the child process number
  2960                              <1> 	;	and it's status (p.stat) is set to active.
  2961                              <1> 	;    3) If the parent had a control tty, the interrupt 
  2962                              <1> 	;	character in that tty buffer is cleared.
  2963                              <1> 	;    4) The child process is put on the lowest priority run 
  2964                              <1> 	;	queue via 'putlu'.
  2965                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  2966                              <1> 	;	it is a unique number) and is put in the child's unique
  2967                              <1> 	;	identifier; process id (p.pid).
  2968                              <1> 	;    6) The process name of the parent is then obtained and
  2969                              <1> 	;	placed in the unique identifier of the parent process
  2970                              <1> 	;	name is then put in 'u.r0'.	
  2971                              <1> 	;    7) The child process is then written out on disk by
  2972                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  2973                              <1> 	;	and the child is born. (The child process is written 
  2974                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  2975                              <1> 	;	number.)
  2976                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  2977                              <1> 	;    9) The child process name is put in 'u.r0'.
  2978                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  2979                              <1> 	;	create the return address for the parent process.
  2980                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  2981                              <1> 	;	the parent has opened. For each file the parent has
  2982                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  2983                              <1> 	;	to indicate that the child process also has opened
  2984                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  2985                              <1> 	;
  2986                              <1> 	; Calling sequence:
  2987                              <1> 	;	from shell ?
  2988                              <1> 	; Arguments:
  2989                              <1> 	;	-
  2990                              <1> 	; Inputs: -
  2991                              <1> 	; Outputs: *u.r0 - child process name
  2992                              <1> 	; ...............................................................
  2993                              <1> 	;	
  2994                              <1> 	; Retro UNIX 8086 v1 modification: 
  2995                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  2996                              <1> 	;	= process id of child a parent process returns
  2997                              <1> 	;	= process id of parent when a child process returns
  2998                              <1> 	;
  2999                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3000                              <1> 	;	in following manner: (with an example: c library, fork)
  3001                              <1> 	;	
  3002                              <1> 	;	1:
  3003                              <1> 	;		sys	fork
  3004                              <1> 	;			br 1f  / child process returns here
  3005                              <1> 	;		bes	2f     / parent process returns here
  3006                              <1> 	;		/ pid of new process in r0
  3007                              <1> 	;		rts	pc
  3008                              <1> 	;	2: / parent process condionally branches here
  3009                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3010                              <1> 	;		rts	pc
  3011                              <1> 	;
  3012                              <1> 	;	1: / child process brances here
  3013                              <1> 	;		clr	r0   / pid = 0 in child process
  3014                              <1> 	;		rts	pc
  3015                              <1> 	;
  3016                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3017                              <1> 	;		// pid = fork();
  3018                              <1> 	;		//
  3019                              <1> 	;		// pid == 0 in child process; 
  3020                              <1> 	;		// pid == -1 means error return
  3021                              <1> 	;		// in child, 
  3022                              <1> 	;		//	parents id is in par_uid if needed
  3023                              <1> 	;		
  3024                              <1> 	;		_fork:
  3025                              <1> 	;			mov	$.fork,eax
  3026                              <1> 	;			int	$0x30
  3027                              <1> 	;			jmp	1f
  3028                              <1> 	;			jnc	2f
  3029                              <1> 	;			jmp	cerror
  3030                              <1> 	;		1:
  3031                              <1> 	;			mov	eax,_par_uid
  3032                              <1> 	;			xor	eax,eax
  3033                              <1> 	;		2:
  3034                              <1> 	;			ret
  3035                              <1> 	;
  3036                              <1> 	;	In Retro UNIX 8086 v1,
  3037                              <1> 	;	'sysfork' returns in following manner:
  3038                              <1> 	;	
  3039                              <1> 	;		mov	ax, sys_fork
  3040                              <1> 	;		mov	bx, offset @f ; routine for child
  3041                              <1> 	;		int	20h
  3042                              <1> 	;		jc	error
  3043                              <1> 	;		
  3044                              <1> 	;	; Routine for parent process here (just after 'jc')
  3045                              <1> 	;		mov	word ptr [pid_of_child], ax
  3046                              <1> 	;		jmp	next_routine_for_parent	
  3047                              <1> 	;
  3048                              <1> 	;	@@: ; routine for child process here				
  3049                              <1> 	;		....	
  3050                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3051                              <1> 	;	       for child process by using BX input.
  3052                              <1> 	;	      (at first, parent process will return then 
  3053                              <1> 	;	      child process will return -after swapped in-
  3054                              <1> 	;	      'syswait' is needed in parent process
  3055                              <1> 	;	      if return from child process will be waited for.)
  3056                              <1> 	;	  				
  3057                              <1> 	
  3058                              <1> ; / create a new process
  3059                              <1> 	; EBX = return address for child process 
  3060                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3061 00003D19 31F6                <1> 	xor 	esi, esi
  3062                              <1> 		; clr r1
  3063                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3064 00003D1B 46                  <1> 	inc	esi
  3065                              <1> 		; inc r1
  3066 00003D1C 80BE[D76D0000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3067                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3068 00003D23 760B                <1> 	jna	short sysfork_2	
  3069                              <1> 		; beq 1f / it's unused so branch
  3070 00003D25 6683FE10            <1> 	cmp	si, nproc
  3071                              <1> 		; cmp r1,$nproc / all processes checked
  3072 00003D29 72F0                <1> 	jb	short sysfork_1
  3073                              <1> 		; blt 1b / no, branch back
  3074                              <1> 	;
  3075                              <1> 	; Retro UNIX 8086 v1. modification:
  3076                              <1> 	;	Parent process returns from 'sysfork' to address 
  3077                              <1> 	;	which is just after 'sysfork' system call in parent
  3078                              <1> 	;	process. Child process returns to address which is put
  3079                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3080                              <1> 	;
  3081                              <1> 		; add $2,18.(sp) / add 2 to pc when trap occured, points
  3082                              <1> 		               ; / to old process return
  3083                              <1> 		; br error1 / no room for a new process
  3084                              <1> sysfork_err:
  3085 00003D2B E9A3FDFFFF          <1> 	jmp	error
  3086                              <1> sysfork_2: ; 1:
  3087 00003D30 E897F0FFFF          <1> 	call	allocate_page
  3088                              <1> 	;jc	error
  3089                              <1> 	; 01/02/2022
  3090 00003D35 72F4                <1> 	jc	short sysfork_err
  3091 00003D37 50                  <1> 	push	eax  ; UPAGE (user structure page) address
  3092                              <1> 	; Retro UNIX 386 v1 modification!
  3093 00003D38 E888F2FFFF          <1> 	call	duplicate_page_dir
  3094                              <1> 		; EAX = New page directory 
  3095 00003D3D 7308                <1> 	jnc	short sysfork_3
  3096 00003D3F 58                  <1> 	pop	eax  ; UPAGE (user structure page) address
  3097 00003D40 E84FF2FFFF          <1> 	call 	deallocate_page
  3098                              <1> 	;jmp	error
  3099                              <1> 	; 01/02/2022
  3100 00003D45 EBE4                <1> 	jmp	short sysfork_err
  3101                              <1> sysfork_3:
  3102                              <1> 	; Retro UNIX 386 v1 modification !
  3103 00003D47 56                  <1> 	push	esi
  3104 00003D48 E8B3110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3105                              <1> 		      ; and interrupt return components (for IRET)
  3106 00003D4D 8705[AF700000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3107 00003D53 A3[B3700000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3108 00003D58 5E                  <1> 	pop	esi
  3109 00003D59 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3110                              <1> 		; [u.usp] = esp
  3111 00003D5A 89F7                <1> 	mov	edi, esi
  3112                              <1> 	;shl	di, 2
  3113                              <1> 	; 12/02/2022
  3114 00003D5C C1E702              <1> 	shl	edi, 2
  3115 00003D5F 8987[E46D0000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3116 00003D65 A3[A6700000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3117                              <1> 	; 28/08/2015
  3118 00003D6A 0FB605[A5700000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3119                              <1> 		; movb u.uno,-(sp) / save parent process number
  3120 00003D71 89C7                <1> 	mov	edi, eax
  3121 00003D73 50                  <1>         push	eax ; ** 
  3122 00003D74 8A87[B76D0000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3123                              <1> 	; 18/09/2015
  3124 00003D7A 8886[B76D0000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3125                              <1> 	; 26/02/2022 (p.waitc is not used)
  3126                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3127                              <1> 	; 25/02/2022 (BugFix)
  3128                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3129                              <1> 	;			   ; ah - reset child's wait channel	
  3130 00003D80 89F0                <1> 	mov	eax, esi
  3131 00003D82 A2[A5700000]        <1> 	mov	[u.uno], al ; child process number
  3132                              <1> 		;movb r1,u.uno / set child process number to r1
  3133 00003D87 FE86[D76D0000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3134                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3135                              <1> 				  ; / process to active status
  3136                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3137                              <1> 			      ; / control tty buffer in r2
  3138                              <1>                 ; beq 2f / branch, if no such tty assigned
  3139                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3140                              <1> 	; 2:
  3141 00003D8D 53                  <1> 	push	ebx  ; * return address for the child process
  3142                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3143                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3144                              <1> 		; mov $runq+4,r2
  3145 00003D8E E8C3110000          <1> 	call	putlu 
  3146                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3147                              <1> 			   ; / run queue
  3148                              <1> 	; 12/02/2022
  3149 00003D93 D1E6                <1> 	shl	esi, 1
  3150                              <1> 	;shl	si, 1
  3151                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3152                              <1> 		       ; / into p.pid table
  3153 00003D95 66FF05[4A700000]    <1> 	inc	word [mpid]
  3154                              <1> 		; inc mpid / increment m.pid; get a new process name
  3155 00003D9C 66A1[4A700000]      <1> 	mov	ax, [mpid]
  3156 00003DA2 668986[766D0000]    <1> 	mov	[esi+p.pid-2], ax
  3157                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3158                              <1> 				    ; / in child process' name slot
  3159 00003DA9 5A                  <1> 	pop	edx  ; * return address for the child process
  3160                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3161 00003DAA 5B                  <1>   	pop	ebx  ; **
  3162                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3163                              <1> 		; movb (sp),r2 / put parent process number in r2
  3164                              <1> 	; 01/02/2022
  3165 00003DAB D0E3                <1> 	shl	bl, 1
  3166                              <1> 	;shl 	bx, 1
  3167                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3168                              <1> 	; ebx <= 32
  3169                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3170 00003DAD 668B83[766D0000]    <1> 	mov	ax, [ebx+p.pid-2]
  3171                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3172                              <1> 				   ; / process
  3173 00003DB4 668986[966D0000]    <1> 	mov	[esi+p.ppid-2], ax
  3174                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3175                              <1> 			  ; / in parent process slot for child
  3176 00003DBB A3[5C700000]        <1> 	mov	[u.r0], eax	
  3177                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3178                              <1> 			     ; / at location where r0 was saved
  3179 00003DC0 8B2D[54700000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3180 00003DC6 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3181                              <1> 			   ; * return address for the child process
  3182                              <1> 		; mov $sysret1,-(sp) /
  3183                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3184                              <1> 			      ; / user is swapped out
  3185                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3186                              <1> 	; 04/09/2015 - 01/09/2015
  3187                              <1> 	; [u.usp] = esp
  3188 00003DC9 68[F33A0000]        <1> 	push	sysret ; ***
  3189 00003DCE 8925[58700000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3190                              <1> 			     ; (for child process)	
  3191 00003DD4 31C0                <1> 	xor 	eax, eax
  3192 00003DD6 66A3[8C700000]      <1> 	mov 	[u.ttyp], ax ; 0
  3193                              <1> 	;
  3194 00003DDC E81F110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3195                              <1> 		;jsr r0,wswap / put child process out on drum
  3196                              <1> 		;jsr r0,unpack / unpack user stack
  3197                              <1> 		;mov u.usp,sp / restore user stack pointer
  3198                              <1> 		; tst (sp)+ / bump stack pointer
  3199                              <1> 	; Retro UNIX 386 v1 modification !
  3200 00003DE1 58                  <1> 	pop	eax ; ***
  3201                              <1> 	;shl	bx, 1
  3202                              <1> 	; 01/02/2022
  3203 00003DE2 D0E3                <1> 	shl	bl, 1 
  3204                              <1> 		; ebx <= 64
  3205 00003DE4 8B83[E46D0000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3206 00003DEA E83A110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3207                              <1> 		      ; registers and return address (for IRET)
  3208                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3209 00003DEF 0FB705[4A700000]    <1>         movzx   eax, word [mpid]
  3210 00003DF6 A3[5C700000]        <1> 	mov	[u.r0], eax
  3211                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3212                              <1> 			       ; / where r0 was saved
  3213                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3214                              <1> 			       ; / process return
  3215                              <1> 	;xor	ebx, ebx
  3216 00003DFB 31F6                <1> 	xor     esi, esi
  3217                              <1> 		;clr r1
  3218                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3219                              <1> 	      ; / opened by the parent process
  3220                              <1> 	; 01/09/2015
  3221                              <1> 	;xor	bh, bh
  3222                              <1> 	;mov 	bl, [esi+u.fp]
  3223 00003DFD 8A86[62700000]      <1> 	mov 	al, [esi+u.fp]
  3224                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3225                              <1>         ;or	bl, bl
  3226 00003E03 08C0                <1> 	or	al, al
  3227 00003E05 740C                <1> 	jz	short sysfork_5	
  3228                              <1> 		; beq 2f / file has not been opened by parent, 
  3229                              <1> 		       ; / so branch
  3230 00003E07 B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3231 00003E09 F6E4                <1> 	mul	ah
  3232                              <1> 	;;movzx	ebx, ax
  3233                              <1> 	;mov	bx, ax
  3234 00003E0B 89C3                <1> 	mov	ebx, eax ; 12/02/2022
  3235                              <1> 	;shl	bx, 3
  3236                              <1> 		; asl r2 / multiply by 8
  3237                              <1>        		; asl r2 / to get index into fsp table
  3238                              <1>        		; asl r2
  3239 00003E0D FE83[266E0000]      <1>   	inc     byte [ebx+fsp-2]
  3240                              <1> 		; incb fsp-2(r2) / increment number of processes
  3241                              <1> 			     ; / using file, because child will now be
  3242                              <1> 			     ; / using this file
  3243                              <1> sysfork_5: ; 2:
  3244 00003E13 46                  <1>         inc     esi
  3245                              <1> 		; inc r1 / get next open file
  3246 00003E14 6683FE0A            <1>         cmp     si, 10
  3247                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3248                              <1> 			    ; / can be opened
  3249 00003E18 72E3                <1> 	jb	short sysfork_4	
  3250                              <1> 		; blt 1b / check next entry
  3251 00003E1A E9D4FCFFFF          <1> 	jmp	sysret
  3252                              <1> 		; br sysret1
  3253                              <1> 
  3254                              <1> sysread: ; < read from file >
  3255                              <1> 	; 27/02/2022
  3256                              <1> 	; 01/02/2022
  3257                              <1> 	; 13/05/2015
  3258                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3259                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3260                              <1> 	;
  3261                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3262                              <1> 	; characters to be read. If finds the file from the file
  3263                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3264                              <1> 	; is returned from a successful open call (sysopen).
  3265                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3266                              <1> 	; is read into core via 'readi'.
  3267                              <1> 	;
  3268                              <1> 	; Calling sequence:
  3269                              <1> 	;	sysread; buffer; nchars
  3270                              <1> 	; Arguments:
  3271                              <1> 	;	buffer - location of contiguous bytes where 
  3272                              <1> 	;		 input will be placed.
  3273                              <1> 	;	nchars - number of bytes or characters to be read.
  3274                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3275                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3276                              <1> 	; ...............................................................
  3277                              <1> 	;				
  3278                              <1> 	; Retro UNIX 8086 v1 modification: 
  3279                              <1> 	;       'sysread' system call has three arguments; so,
  3280                              <1> 	;	* 1st argument, file descriptor is in BX register
  3281                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3282                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3283                              <1> 	;
  3284                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3285                              <1> 	;	to the user with number of bytes read. 
  3286                              <1> 	;
  3287 00003E1F E840000000          <1> 	call	rw1
  3288                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3289                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3290                              <1>        	; 27/02/2022
  3291 00003E24 7239                <1> 	jc	short sysread_err
  3292 00003E26 F6C480              <1> 	test	ah, 80h
  3293                              <1> 		; tst r1 / negative i-number?
  3294                              <1> 	;jnz	error
  3295                              <1> 		; ble error1 / yes, error 1 to read
  3296                              <1> 			   ; / it should be positive
  3297                              <1> 	; 01/02/2022
  3298                              <1> 	;jnz	short rw_error
  3299                              <1> 	;27/02/2022
  3300 00003E29 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3301                              <1> 	;
  3302 00003E2B E88D150000          <1> 	call	readi
  3303                              <1> 		; jsr r0,readi / read data into core
  3304 00003E30 EB14                <1> 	jmp	short rw0
  3305                              <1> 		; br 1f
  3306                              <1> 
  3307                              <1> syswrite: ; < write to file >
  3308                              <1> 	; 27/02/2022
  3309                              <1> 	; 01/02/2022
  3310                              <1> 	; 13/05/2015
  3311                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3312                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3313                              <1> 	;
  3314                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3315                              <1> 	; and the number of characters to write. If finds the file
  3316                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3317                              <1> 	; descriptor is returned from a successful open or create call
  3318                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3319                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3320                              <1> 	;
  3321                              <1> 	; Calling sequence:
  3322                              <1> 	;	syswrite; buffer; nchars
  3323                              <1> 	; Arguments:
  3324                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3325                              <1> 	;	nchars - number of characters to be written.
  3326                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3327                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3328                              <1> 	; ...............................................................
  3329                              <1> 	;				
  3330                              <1> 	; Retro UNIX 8086 v1 modification: 
  3331                              <1> 	;       'syswrite' system call has three arguments; so,
  3332                              <1> 	;	* 1st argument, file descriptor is in BX register
  3333                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3334                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3335                              <1> 	;
  3336                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3337                              <1> 	;	to the user with number of bytes written. 
  3338                              <1> 	;
  3339 00003E32 E82D000000          <1> 	call	rw1
  3340                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3341                              <1> 		; jsr r0,rw1 / get i-number in r1 of file to write
  3342                              <1> 	; 01/02/2022
  3343                              <1> 	;jnc	short syswrite_1
  3344                              <1> ;rw_error:
  3345                              <1> 	;jmp	error
  3346                              <1> 	; 27/02/2022
  3347 00003E37 7226                <1> 	jc	short short syswrite_err
  3348                              <1> syswrite_1:
  3349 00003E39 F6C480              <1>         test	ah, 80h
  3350                              <1> 		; tst r1 / positive i-number ?
  3351 00003E3C 7417                <1>         jz	short rw3 ; 13/05/2015
  3352                              <1> 	;jz	error
  3353                              <1> 		; bge error1 / yes, error 1 
  3354                              <1> 			   ; / negative i-number means write
  3355 00003E3E 66F7D8              <1> 	neg	ax
  3356                              <1> 		; neg r1 / make it positive
  3357 00003E41 E865170000          <1> 	call	writei
  3358                              <1>         	; jsr r0,writei / write data
  3359                              <1> rw0: ; 1:
  3360 00003E46 A1[84700000]        <1>         mov	eax, [u.nread]
  3361 00003E4B A3[5C700000]        <1> 	mov	[u.r0], eax
  3362                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3363                              <1> 				  ; / into (u.r0)
  3364 00003E50 E99EFCFFFF          <1> 	jmp	sysret
  3365                              <1>         	; br sysret1
  3366                              <1> rw3: 
  3367                              <1> 	; 13/05/2015
  3368 00003E55 C705[AB700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3368 00003E5D 0000                <1>
  3369                              <1> 	;stc
  3370                              <1> 	;retn
  3371                              <1> 	; 27/02/2022 (BugFix)
  3372                              <1> sysread_err:
  3373                              <1> syswrite_err:
  3374 00003E5F E96FFCFFFF          <1> 	jmp	error
  3375                              <1> 
  3376                              <1> rw1:	
  3377                              <1> 	; 14/05/2015
  3378                              <1> 	; 13/05/2015
  3379                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3380                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3381                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3382                              <1> 	;
  3383                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3384                              <1> 				;(in the user's virtual memory space)
  3385                              <1> 	;mov	[u.count], edx 
  3386                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3387                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3388                              <1> 	;;mov	eax, ebx ; file descriptor
  3389                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3390                              <1> 		             ; / (index to u.fp table) in r1
  3391                              <1> 	; 13/05/2015
  3392 00003E64 C705[5C700000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3392 00003E6C 0000                <1>
  3393                              <1> 	;
  3394                              <1> 	;; call	getf
  3395                              <1>         ; eBX = File descriptor
  3396 00003E6E E82E0B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3397                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3398                              <1> 	; AX = I-number of the file ; negative i-number means write
  3399                              <1> 	; 13/05/2015
  3400 00003E73 6683F801            <1> 	cmp 	ax, 1
  3401 00003E77 7217                <1> 	jb	short rw2
  3402                              <1> 	;
  3403 00003E79 890D[7C700000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3404                              <1> 				;(in the user's virtual memory space)
  3405 00003E7F 8915[80700000]      <1> 	mov	[u.count], edx 
  3406                              <1> 	; 14/05/2015
  3407 00003E85 C705[AB700000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3407 00003E8D 0000                <1>
  3408 00003E8F C3                  <1> 	retn
  3409                              <1>         	; rts r0
  3410                              <1> rw2:
  3411                              <1> 	; 13/05/2015
  3412 00003E90 C705[AB700000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3412 00003E98 0000                <1>
  3413 00003E9A C3                  <1> 	retn
  3414                              <1> 
  3415                              <1> sysopen: ;<open file>
  3416                              <1> 	; 12/02/2022
  3417                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3418                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3419                              <1> 	;
  3420                              <1> 	; 'sysopen' opens a file in following manner:
  3421                              <1> 	;    1) The second argument in a sysopen says whether to
  3422                              <1> 	;	open the file ro read (0) or write (>0).
  3423                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3424                              <1> 	;    3) The file is opened by 'iopen'.
  3425                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3426                              <1> 	;	and the user's open file list - u.fp.
  3427                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3428                              <1> 	;	b) An entry for the file is created in the fsp table.
  3429                              <1> 	;	c) The number of this entry is put on u.fp list.
  3430                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3431                              <1> 	;	   to by u.r0.
  3432                              <1> 	;
  3433                              <1> 	; Calling sequence:
  3434                              <1> 	;	sysopen; name; mode
  3435                              <1> 	; Arguments:
  3436                              <1> 	;	name - file name or path name
  3437                              <1> 	;	mode - 0 to open for reading
  3438                              <1> 	;	       1 to open for writing
  3439                              <1> 	; Inputs: (arguments)
  3440                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3441                              <1> 	;		  is put into r0's location on the stack.	
  3442                              <1> 	; ...............................................................
  3443                              <1> 	;				
  3444                              <1> 	; Retro UNIX 8086 v1 modification: 
  3445                              <1> 	;       'sysopen' system call has two arguments; so,
  3446                              <1> 	;	* 1st argument, name is pointed to by BX register
  3447                              <1> 	;	* 2nd argument, mode is in CX register
  3448                              <1> 	;
  3449                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3450                              <1> 	;	to the user with the file descriptor/number 
  3451                              <1> 	;	(index to u.fp list).
  3452                              <1> 	;
  3453                              <1> 	;call	arg2
  3454                              <1> 	; * name - 'u.namep' points to address of file/path name
  3455                              <1> 	;          in the user's program segment ('u.segmnt')
  3456                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3457                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3458                              <1> 	;          which is on top of stack.
  3459                              <1> 	;
  3460                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3461                              <1> 	;
  3462                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3463                              <1> 
  3464 00003E9B 891D[74700000]      <1> 	mov	[u.namep], ebx
  3465                              <1> 	;push	cx
  3466 00003EA1 51                  <1> 	push	ecx ; 12/02/2022
  3467 00003EA2 E82D0B0000          <1> 	call	namei
  3468                              <1> 		; jsr r0,namei / i-number of file in r1
  3469                              <1>      	;and	ax, ax
  3470                              <1> 	;jz	error ; File not found
  3471 00003EA7 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3472                              <1> 	;jc	error ; 27/05/2013
  3473                              <1> 		; br  error2 / file not found
  3474                              <1>    	;pop	dx ; mode
  3475                              <1> 	;push	dx
  3476                              <1> 	; 12/02/2022
  3477                              <1> 	;pop	edx ; * ; mode
  3478                              <1> 	;push	edx ; *
  3479 00003EA9 8B1424              <1> 	mov	edx, [esp] ; *
  3480                              <1> 	; edx = open mode (0 or 1)
  3481                              <1> 	;or	dx, dx
  3482 00003EAC 08D2                <1> 	or	dl, dl
  3483                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3484                              <1> 		         ; / 0 means, open for read)
  3485 00003EAE 7403                <1> 	jz	short sysopen_0
  3486                              <1> 		; beq 1f / yes, leave i-number positive
  3487                              <1> syscreat_0: 
  3488                              <1> 	; 12/02/2022 (v1.0, 2022) ; 27/12/2015 (v1.1)
  3489 00003EB0 66F7D8              <1> 	neg	ax
  3490                              <1>         	; neg r1 / open for writing so make i-number negative
  3491                              <1> sysopen_0: ;1:
  3492 00003EB3 E88B1B0000          <1> 	call	iopen
  3493                              <1> 		; jsr r0,iopen / open file whose i-number is in r1
  3494 00003EB8 5A                  <1> 	pop	edx ; * ; mode ; 12/02/2022
  3495                              <1> 	;and	dx, dx
  3496 00003EB9 20D2                <1> 	and	dl, dl
  3497                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3498 00003EBB 7403                <1> 	jz	short sysopen_2
  3499                              <1>         	; beq op1 / is open for read op1
  3500                              <1> sysopen_1: ;op0:
  3501 00003EBD 66F7D8              <1> 	neg	ax
  3502                              <1>         	; neg r1 
  3503                              <1> 		     ;/ make i-number positive if open for writing [???]
  3504                              <1> 	;; NOTE: iopen always make i-number positive.
  3505                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3506                              <1> sysopen_2: ;op1:
  3507 00003EC0 31F6                <1>         xor     esi, esi
  3508                              <1>         	; clr r2 / clear registers
  3509 00003EC2 31DB                <1>         xor     ebx, ebx
  3510                              <1> 		; clr r3
  3511                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3512 00003EC4 389E[62700000]      <1>         cmp     [esi+u.fp], bl ; 0
  3513                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3514 00003ECA 7625                <1>         jna	short sysopen_4
  3515                              <1> 		; beq 1f / if byte in list is 0 branch
  3516 00003ECC 46                  <1>         inc     esi
  3517                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3518 00003ECD 6683FE0A            <1>         cmp     si, 10
  3519                              <1> 		; cmp r2,$10. / reached end of list?
  3520 00003ED1 72F1                <1> 	jb	short sysopen_3
  3521                              <1> 		; blt 1b / no, go back
  3522                              <1> toomanyf:
  3523                              <1> 	; 14/05/2015
  3524 00003ED3 C705[AB700000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3524 00003EDB 0000                <1>
  3525 00003EDD E9F1FBFFFF          <1> 	jmp	error
  3526                              <1>         	; br error2 / yes, error (no files open)
  3527                              <1> fnotfound: 
  3528                              <1> 	; 14/05/2015
  3529 00003EE2 C705[AB700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3529 00003EEA 0000                <1>
  3530 00003EEC E9E2FBFFFF          <1> 	jmp	error
  3531                              <1> 
  3532                              <1> sysopen_4: ; 1:
  3533 00003EF1 6683BB[286E0000]00  <1>         cmp     word [ebx+fsp], 0
  3534                              <1> 		; tst fsp(r3) / scan fsp entries
  3535 00003EF9 7610                <1>         jna     short sysopen_5
  3536                              <1> 		; beq 1f / if 0 branch
  3537                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3538 00003EFB 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3539                              <1> 		; add $8.,r3 / add 8 to r3 
  3540                              <1> 			; / to bump it to next entry mfsp table
  3541 00003EFF 6681FBF401          <1>         cmp     bx, nfiles*10
  3542                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3543 00003F04 72EB                <1> 	jb	short sysopen_4
  3544                              <1>        		; blt 1b / no, back
  3545 00003F06 E9C8FBFFFF          <1> 	jmp	error
  3546                              <1>         	; br error2 / yes, error
  3547                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3548 00003F0B 668983[286E0000]    <1>         mov     [ebx+fsp], ax
  3549                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3550                              <1> 			; / into next available entry in fsp table,
  3551                              <1> 	; 12/02/2022
  3552                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3553                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3554                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3555                              <1> 	;xor	edi, edi
  3556                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3557                              <1> 	;	; clr fsp+4(r3)
  3558                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3559                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3560 00003F12 31C0                <1> 	xor	eax, eax
  3561 00003F14 8983[2C6E0000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3562 00003F1A 668983[306E0000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3563                              <1> 
  3564 00003F21 66A1[40700000]      <1> 	mov	ax, [cdev]
  3565 00003F27 668983[2A6E0000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3566                              <1> 
  3567 00003F2E 89D8                <1>   	mov	eax, ebx
  3568 00003F30 B30A                <1> 	mov	bl, 10
  3569 00003F32 F6F3                <1> 	div	bl 
  3570                              <1> 		; asr r3
  3571                              <1> 		; asr r3 / divide by 8 
  3572                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3573 00003F34 FEC0                <1> 	inc	al
  3574                              <1>         	; inc r3 / add 1 to get fsp entry number
  3575 00003F36 8886[62700000]      <1>         mov     [esi+u.fp], al
  3576                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3577                              <1> 			; / next available slot in u.fp list
  3578 00003F3C 8935[5C700000]      <1>         mov     [u.r0], esi
  3579                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3580                              <1> 			     ; / into r0 loc on stack
  3581 00003F42 E9ACFBFFFF          <1>         jmp	sysret
  3582                              <1> 		; br sysret2
  3583                              <1> 
  3584                              <1> 	;
  3585                              <1> 	; 'fsp' table (10 bytes/entry)
  3586                              <1> 	; bit 15				   bit 0
  3587                              <1> 	; ---|-------------------------------------------
  3588                              <1> 	; r/w|		i-number of open file
  3589                              <1> 	; ---|-------------------------------------------
  3590                              <1> 	;		   device number
  3591                              <1> 	; -----------------------------------------------
  3592                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3593                              <1> 	; -----------------------------------------------
  3594                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3595                              <1> 	; ----------------------|------------------------
  3596                              <1> 	;  flag that says file 	| number of processes
  3597                              <1> 	;   has been deleted	| that have file open 
  3598                              <1> 	; ----------------------|------------------------
  3599                              <1> 	;
  3600                              <1> 
  3601                              <1> syscreat: ; < create file >
  3602                              <1> 	; 12/02/2022
  3603                              <1> 	; 01/02/2022
  3604                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3605                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3606                              <1> 	;
  3607                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3608                              <1> 	; u.namep points to name of the file and mode is put
  3609                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3610                              <1> 	; If the file aready exists, it's mode and owner remain 
  3611                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3612                              <1> 	; did not exist, an i-node is created with the new mode via
  3613                              <1> 	; 'maknod' whether or not the file already existed, it is
  3614                              <1> 	; open for writing. The fsp table is then searched for a free
  3615                              <1> 	; entry. When a free entry is found, proper data is placed
  3616                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3617                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3618                              <1> 	; is put in the user's r0. 			
  3619                              <1> 	;
  3620                              <1> 	; Calling sequence:
  3621                              <1> 	;	syscreate; name; mode
  3622                              <1> 	; Arguments:
  3623                              <1> 	;	name - name of the file to be created
  3624                              <1> 	;	mode - mode of the file to be created
  3625                              <1> 	; Inputs: (arguments)
  3626                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3627                              <1> 	;		   (the file descriptor of new file)
  3628                              <1> 	; ...............................................................
  3629                              <1> 	;				
  3630                              <1> 	; Retro UNIX 8086 v1 modification: 
  3631                              <1> 	;       'syscreate' system call has two arguments; so,
  3632                              <1> 	;	* 1st argument, name is pointed to by BX register
  3633                              <1> 	;	* 2nd argument, mode is in CX register
  3634                              <1> 	;
  3635                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3636                              <1> 	;	to the user with the file descriptor/number 
  3637                              <1> 	;	(index to u.fp list).
  3638                              <1> 	;
  3639                              <1> 	;call	arg2
  3640                              <1> 	; * name - 'u.namep' points to address of file/path name
  3641                              <1> 	;          in the user's program segment ('u.segmnt')
  3642                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3643                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3644                              <1> 	;          which is on top of stack.
  3645                              <1> 	;
  3646                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3647                              <1> 			    ; / on stack
  3648 00003F47 891D[74700000]      <1> 	mov	[u.namep], ebx ; file name address
  3649                              <1> 	;push	cx ; mode
  3650                              <1> 	; 01/02/2022
  3651 00003F4D 51                  <1> 	push	ecx ; mode
  3652 00003F4E E8810A0000          <1> 	call 	namei        	
  3653                              <1> 		; jsr r0,namei / get the i-number
  3654                              <1>         ;and	ax, ax
  3655                              <1> 	;jz	short syscreat_2	       	
  3656 00003F53 721B                <1> 	jc	short syscreat_2
  3657                              <1> 		; br  2f / if file doesn't exist 2f
  3658                              <1> 	; 12/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18, 2022)
  3659                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3660 00003F55 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3661                              <1>         ;jb	syscreat_0 ; yes
  3662                              <1> 	; 02/02/2022
  3663 00003F59 7305                <1> 	jnb	short syscreat_1
  3664 00003F5B E950FFFFFF          <1> 	jmp	syscreat_0
  3665                              <1> syscreat_1:
  3666 00003F60 66F7D8              <1> 	neg 	ax
  3667                              <1>         	; neg r1 / if file already exists make i-number 
  3668                              <1> 		       ; / negative (open for writing)
  3669 00003F63 E8DB1A0000          <1> 	call	iopen
  3670                              <1>         	; jsr r0,iopen /
  3671 00003F68 E8A8130000          <1> 	call	itrunc
  3672                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3673                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3674                              <1> 	; 01/02/2022
  3675 00003F6D 59                  <1> 	pop	ecx ; mode
  3676                              <1> 	; 12/02/2022
  3677 00003F6E EB0E                <1> 	jmp	short syscreat_3
  3678                              <1>         ;jmp	sysopen_1
  3679                              <1>         	; br op0
  3680                              <1> syscreat_2: ; 2: / file doesn't exist
  3681                              <1> 	; 01/02/2022
  3682 00003F70 58                  <1> 	pop	eax ; mode
  3683                              <1> 	;pop	ax
  3684                              <1>         	; mov (sp)+,r1 / put the mode in r1
  3685 00003F71 30E4                <1> 	xor	ah, ah	
  3686                              <1>         	; bic $!377,r1 / clear upper byte
  3687 00003F73 E86D0D0000          <1> 	call 	maknod
  3688                              <1>         	; jsr r0,maknod / make an i-node for this file
  3689 00003F78 66A1[8E700000]      <1> 	mov	ax, [u.dirbuf]
  3690                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3691                              <1> 			        ; / for this new file in r1
  3692                              <1> syscreat_3:
  3693 00003F7E E93AFFFFFF          <1>         jmp     sysopen_1
  3694                              <1>         	; br op0 / open the file
  3695                              <1> 
  3696                              <1> sysmkdir: ; < make directory >
  3697                              <1> 	; 01/02/2022
  3698                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3699                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3700                              <1> 	;
  3701                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3702                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3703                              <1> 	; The special entries '.' and '..' are not present.
  3704                              <1> 	; Errors are indicated if the directory already exists or		
  3705                              <1> 	; user is not the super user. 
  3706                              <1> 	;
  3707                              <1> 	; Calling sequence:
  3708                              <1> 	;	sysmkdir; name; mode
  3709                              <1> 	; Arguments:
  3710                              <1> 	;	name - points to the name of the directory
  3711                              <1> 	;	mode - mode of the directory
  3712                              <1> 	; Inputs: (arguments)
  3713                              <1> 	; Outputs: -
  3714                              <1> 	;    (sets 'directory' flag to 1; 
  3715                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3716                              <1> 	; ...............................................................
  3717                              <1> 	;				
  3718                              <1> 	; Retro UNIX 8086 v1 modification: 
  3719                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3720                              <1> 	;	* 1st argument, name is pointed to by BX register
  3721                              <1> 	;	* 2nd argument, mode is in CX register
  3722                              <1> 		
  3723                              <1> ; / make a directory
  3724                              <1> 	
  3725                              <1> 	;call	arg2
  3726                              <1> 	; * name - 'u.namep' points to address of file/path name
  3727                              <1> 	;          in the user's program segment ('u.segmnt')
  3728                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3729                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3730                              <1> 	;          which is on top of stack.
  3731                              <1> 
  3732                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3733                              <1> 			    ; / on stack
  3734 00003F83 891D[74700000]      <1> 	mov	[u.namep], ebx
  3735                              <1> 	;push	cx ; mode
  3736                              <1> 	; 01/02/2022
  3737 00003F89 51                  <1> 	push	ecx ; mode
  3738 00003F8A E8450A0000          <1> 	call	namei
  3739                              <1>         	; jsr r0,namei / get the i-number
  3740                              <1>         	;     br .+4 / if file not found branch around error
  3741                              <1>         ;xor 	ax, ax
  3742                              <1> 	;jnz	error
  3743 00003F8F 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3744                              <1> 	;jnc	error	
  3745                              <1> 		; br  error2 / directory already exists (error)
  3746 00003F91 803D[A2700000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3747                              <1>         	;tstb u.uid / is user the super user
  3748                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3749                              <1> 	;;jna	error
  3750                              <1> 	; 01/02/2022 (BugFix)
  3751 00003F98 7721                <1> 	ja	short dir_access_err
  3752                              <1>         	;bne error2 / no, not allowed
  3753                              <1> 	;pop	ax
  3754                              <1> 	; 01/02/2022
  3755 00003F9A 58                  <1> 	pop	eax ; mode
  3756                              <1>         	;mov (sp)+,r1 / put the mode in r1
  3757 00003F9B 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3758                              <1>         	;bic $!317,r1 / all but su and ex
  3759                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3760 00003F9F 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3761                              <1>         	;bis $40000,r1 / directory flag
  3762 00003FA2 E83E0D0000          <1> 	call	maknod
  3763                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3764                              <1> sysclose_sysret: ; 01/02/2022
  3765 00003FA7 E947FBFFFF          <1> 	jmp	sysret
  3766                              <1>         	;br sysret2 /
  3767                              <1> dir_exists:
  3768                              <1> 	; 14/05/2015
  3769 00003FAC C705[AB700000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3769 00003FB4 0000                <1>
  3770 00003FB6 E918FBFFFF          <1> 	jmp	error
  3771                              <1> dir_access_err:
  3772                              <1> 	; 14/05/2015
  3773 00003FBB C705[AB700000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3773 00003FC3 0000                <1>
  3774 00003FC5 E909FBFFFF          <1> 	jmp	error
  3775                              <1> 
  3776                              <1> sysclose: ;<close file>
  3777                              <1> 	; 01/02/2022
  3778                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3779                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3780                              <1> 	;
  3781                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3782                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3783                              <1> 	; is put in r1 and 'fclose' is called.
  3784                              <1> 	;
  3785                              <1> 	; Calling sequence:
  3786                              <1> 	;	sysclose
  3787                              <1> 	; Arguments:
  3788                              <1> 	;	-  
  3789                              <1> 	; Inputs: *u.r0 - file descriptor
  3790                              <1> 	; Outputs: -
  3791                              <1> 	; ...............................................................
  3792                              <1> 	;				
  3793                              <1> 	; Retro UNIX 8086 v1 modification:
  3794                              <1> 	;	 The user/application program puts file descriptor
  3795                              <1> 	;        in BX register as 'sysclose' system call argument.
  3796                              <1> 	; 	 (argument transfer method 1)
  3797                              <1> 
  3798                              <1> 	; / close the file
  3799                              <1> 	
  3800 00003FCA 89D8                <1> 	mov 	eax, ebx
  3801 00003FCC E88D090000          <1> 	call 	fclose
  3802                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3803                              <1> 		; jsr r0,fclose / close the file
  3804                              <1>                	; br error2 / unknown file descriptor
  3805                              <1> 		; br sysret2
  3806                              <1> 	; 14/05/2015
  3807                              <1> 	;jnc	sysret
  3808                              <1> 	; 01/02/2022
  3809 00003FD1 73D4                <1> 	jnc	short sysclose_sysret
  3810 00003FD3 C705[AB700000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3810 00003FDB 0000                <1>
  3811 00003FDD E9F1FAFFFF          <1> 	jmp	error
  3812                              <1> 
  3813                              <1> sysemt:
  3814                              <1> 	; 23/02/2022
  3815                              <1> 	; 01/02/2022
  3816                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3817                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3818                              <1> 	;
  3819                              <1> 	; Retro UNIX 8086 v1 modification: 
  3820                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3821                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3822                              <1> 	;
  3823                              <1> 	; Retro UNIX 8086 v1 feature only!
  3824                              <1> 	;	Using purpose: Kernel will start without time-out
  3825                              <1> 	;	(internal clock/timer) functionality.
  3826                              <1> 	;	Then etc/init will enable clock/timer for
  3827                              <1> 	;	multi tasking. (Then it will not be disabled again
  3828                              <1> 	;	except hardware reset/restart.)
  3829                              <1> 
  3830 00003FE2 803D[A2700000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3831                              <1> 	;;ja	error
  3832                              <1> 	;ja	badsys ; 14/05/2015
  3833                              <1> 	; 01/02/2022
  3834                              <1> 	;jna	short emt_0
  3835                              <1> 	;jmp	badsys
  3836 00003FE9 773A                <1> 	ja	short sysilgins ; jmp badsys
  3837                              <1> emt_0:
  3838 00003FEB FA                  <1> 	cli
  3839 00003FEC 21DB                <1> 	and	ebx, ebx
  3840 00003FEE 7429                <1> 	jz	short emt_2
  3841                              <1> 	; Enable multi tasking -time sharing-
  3842 00003FF0 B8[9E4F0000]        <1> 	mov	eax, clock ; enable multi tasking clock/timer
  3843                              <1> 	; 23/02/2022
  3844 00003FF5 BA[620A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3845                              <1> emt_1:
  3846 00003FFA A3[28070000]        <1> 	mov	[x_timer], eax
  3847                              <1> 	; 23/02/2022 (Temporary)
  3848 00003FFF 8915[2C070000]      <1> 	mov	[x_rtci], edx
  3849 00004005 B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3850 00004007 E853020000          <1> 	call	wttyc  ; clear video page
  3851 0000400C B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3852 0000400E E84C020000          <1> 	call	wttyc  ; clear video page
  3853                              <1> 	;
  3854 00004013 FB                  <1> 	sti
  3855 00004014 E9DAFAFFFF          <1> 	jmp	sysret
  3856                              <1> emt_2:
  3857                              <1> 	; Disable multi tasking -time sharing-
  3858 00004019 B8[34070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3859                              <1> 	; 23/02/2022
  3860 0000401E BA[690A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3861                              <1> 	;
  3862 00004023 EBD5                <1> 	jmp	short emt_1
  3863                              <1> 
  3864                              <1> 	; Original UNIX v1 'sysemt' routine
  3865                              <1> ;sysemt:
  3866                              <1>         ;
  3867                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3868                              <1> 			 ; / in loc 30
  3869                              <1>         ;cmp    30,$core / was the argument a lower address 
  3870                              <1> 			; / than core
  3871                              <1>         ;blo    1f / yes, rtssym
  3872                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3873                              <1> 			; / and less than "ecore"
  3874                              <1>         ;blo    2f / yes, sysret2
  3875                              <1> ;1:
  3876                              <1>         ;mov    $rtssym,30
  3877                              <1> ;2:
  3878                              <1>         ;br     sysret2
  3879                              <1> 
  3880                              <1> 	; 01/02/2022
  3881                              <1> sysilgins:
  3882                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3883                              <1> 	; 03/06/2013
  3884                              <1> 	; Retro UNIX 8086 v1 modification: 
  3885                              <1> 	;	not a valid system call ! (not in use)
  3886                              <1> 	;
  3887 00004025 E952FBFFFF          <1> 	jmp	badsys
  3888                              <1> 	;jmp	error
  3889                              <1> 	;;jmp 	sysret
  3890                              <1> 
  3891                              <1> 	; Original UNIX v1 'sysemt' routine
  3892                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3893                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3894                              <1> 			  ;/ put it in loc 8.,
  3895                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3896                              <1> 		       ; / trap address
  3897                              <1>         ;blo    1f / is the address a user core address?  
  3898                              <1> 		; / yes, go to 2f
  3899                              <1>         ;cmp    10,$ecore
  3900                              <1>         ;blo    2f
  3901                              <1> ;1:
  3902                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3903                              <1> 		    ; / instruction trap address for the system
  3904                              <1> ;2:
  3905                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3906                              <1> 
  3907                              <1> sysmdate: ; < change the modification time of a file >
  3908                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3909                              <1> 	;	(ECX input)
  3910                              <1> 	; 01/02/2022
  3911                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3912                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3913                              <1> 	;
  3914                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3915                              <1> 	; file into core. The user is checked if he is the owner 
  3916                              <1> 	; or super user. If he is neither an error occurs.
  3917                              <1> 	; 'setimod' is then called to set the i-node modification
  3918                              <1> 	; byte and the modification time, but the modification time
  3919                              <1> 	; is overwritten by whatever get put on the stack during
  3920                              <1> 	; a 'systime' system call. This calls are restricted to
  3921                              <1> 	; the super user.		
  3922                              <1> 	;
  3923                              <1> 	; Calling sequence:
  3924                              <1> 	;	sysmdate; name
  3925                              <1> 	; Arguments:
  3926                              <1> 	;	name - points to the name of file
  3927                              <1> 	; Inputs: (arguments)
  3928                              <1> 	; Outputs: -
  3929                              <1> 	; ...............................................................
  3930                              <1> 	;				
  3931                              <1> 	; Retro UNIX 8086 v1 modification: 
  3932                              <1> 	;	 The user/application program puts address 
  3933                              <1> 	;	 of the file name in BX register 
  3934                              <1> 	;	 as 'sysmdate' system call argument.
  3935                              <1> 	;
  3936                              <1> ; / change the modification time of a file
  3937                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3938 0000402A 891D[74700000]      <1>         mov	[u.namep], ebx
  3939                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  3940 00004030 890D[E06C0000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  3941 00004036 E899090000          <1> 	call	namei
  3942                              <1> 		; jsr r0,namei / get its i-number
  3943                              <1> 	;;jc	error       
  3944                              <1> 		; br error2 / no, such file
  3945                              <1> 	;jc	fnotfound ; file not found !
  3946                              <1> 	; 01/02/2022
  3947 0000403B 7305                <1> 	jnc	short mdate_0
  3948 0000403D E9A0FEFFFF          <1> 	jmp	fnotfound
  3949                              <1> mdate_0:
  3950 00004042 E8A2110000          <1> 	call	iget
  3951                              <1> 		; jsr r0,iget / get i-node into core
  3952 00004047 A0[A2700000]        <1> 	mov	al, [u.uid]
  3953 0000404C 3A05[5B6D0000]      <1> 	cmp	al, [i.uid]
  3954                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  3955 00004052 7413                <1> 	je	short mdate_1
  3956                              <1>         	; beq 1f / yes
  3957 00004054 20C0                <1> 	and	al, al
  3958                              <1> 		; tstb u.uid / no, is user the super user
  3959                              <1> 	;jnz	error
  3960                              <1> 		; bne error2 / no, error
  3961 00004056 740F                <1> 	jz	short mdate_1
  3962 00004058 C705[AB700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3962 00004060 0000                <1>
  3963                              <1> sysstty_err:	; 01/02/2022
  3964 00004062 E96CFAFFFF          <1> 	jmp	error
  3965                              <1> mdate_1: ;1:
  3966 00004067 E887120000          <1> 	call	setimod
  3967                              <1>         	; jsr r0,setimod / fill in modification data,
  3968                              <1> 		               ; / time etc.
  3969 0000406C BE[E06C0000]        <1> 	mov	esi, p_time
  3970 00004071 BF[726D0000]        <1> 	mov	edi, i.mtim
  3971 00004076 A5                  <1> 	movsd
  3972                              <1> 		; mov 4(sp),i.mtim / move present time to
  3973                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  3974 00004077 E977FAFFFF          <1>         jmp	sysret
  3975                              <1> 		; br sysret2
  3976                              <1> 
  3977                              <1> 	; 01/02/2022
  3978                              <1> sysstty_err_s:
  3979 0000407C 880D[5C700000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  3980 00004082 EBDE                <1> 	jmp	short sysstty_err
  3981                              <1> 
  3982                              <1> sysstty: ; < set tty status and mode >
  3983                              <1> 	; 23/02/2022
  3984                              <1> 	; 22/02/2022
  3985                              <1> 	; 02/02/2022
  3986                              <1> 	; 01/02/2022 (clear screen)
  3987                              <1> 	; 17/11/2015
  3988                              <1> 	; 12/11/2015
  3989                              <1> 	; 29/10/2015
  3990                              <1> 	; 17/10/2015
  3991                              <1> 	; 13/10/2015
  3992                              <1> 	; 29/06/2015
  3993                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  3994                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  3995                              <1> 	;
  3996                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  3997                              <1> 	; whose file descriptor is in (u.r0).
  3998                              <1> 	;
  3999                              <1> 	; Calling sequence:
  4000                              <1> 	;	sysstty; arg
  4001                              <1> 	; Arguments:
  4002                              <1> 	;	arg - address of 3 consequitive words that contain
  4003                              <1> 	;	      the source of status data	
  4004                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4005                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4006                              <1> 	; ...............................................................
  4007                              <1> 	;	
  4008                              <1> 	; Retro UNIX 8086 v1 modification: 
  4009                              <1> 	;	'sysstty' system call will set the tty
  4010                              <1> 	;	(clear keyboard buffer and set cursor position)
  4011                              <1> 	;	 in following manner:
  4012                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4013                              <1> 	;
  4014                              <1> 	; Inputs:
  4015                              <1> 	;	BX = 0 --> means
  4016                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4017                              <1> 	;	      set cursor position for console tty, only 
  4018                              <1> 	;	      CH will be ignored (char. will not be written)	
  4019                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4020                              <1> 	;	      set console tty for (current) process
  4021                              <1> 	;	      CL = tty number (0 to 9)
  4022                              <1> 	;	      (If CH = 0, character will not be written)
  4023                              <1> 	;          If CH > 0 (CL < FFh)	
  4024                              <1> 	;             CL = tty number (0 to 9)
  4025                              <1> 	;	      CH = character will be written
  4026                              <1> 	;	        at requested cursor position (in DX)	
  4027                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4028                              <1>   	;		(only tty number 0 to 7) 
  4029                              <1> 	;          DL = communication parameters (for serial ports) 
  4030                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4031                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4032                              <1> 	;			or set cursor position	
  4033                              <1> 	;	   DH = 0FFh -> DL is not valid
  4034                              <1> 	;		do not set serial port parameters 
  4035                              <1> 	;		or do not set cursor position
  4036                              <1> 	;
  4037                              <1> 	;	BX > 0 --> points to name of tty
  4038                              <1> 	;    	   CH > 0 -->
  4039                              <1> 	;		CH = character will be written in current 
  4040                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4041                              <1> 	;	     	or character will be sent to serial port
  4042                              <1> 	;	     	(for tty number 8 or 9)
  4043                              <1> 	;		CL = color of the character if tty number < 8.
  4044                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4045                              <1> 	;		set mode (tty 8 to 9) or 
  4046                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4047                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4048                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4049                              <1> 	;		(DL is not valid)
  4050                              <1> 	;	   DL = communication parameters 
  4051                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4052                              <1> 	;
  4053                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4054                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4055                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4056                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4057                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4058                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4059                              <1> 	;
  4060                              <1> 	; Outputs:
  4061                              <1> 	;	cf = 0 -> OK
  4062                              <1> 	;	     AL = tty number (0 to 9)
  4063                              <1> 	;	     AH = line status if tty number is 8 or 9
  4064                              <1> 	;	     AH = process number (of the caller) 	
  4065                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4066                              <1> 	;	     AH = FFh if the tty is locked 
  4067                              <1> 	;		  (owned by another process)
  4068                              <1> 	;	        = process number (of the caller) 
  4069                              <1> 	;		  (if < FFh and tty number < 8)
  4070                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4071                              <1> 	;	     AH = line status if tty number is 8 or 9
  4072                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4073                              <1> 	;	
  4074                              <1> 
  4075                              <1> 	; 27/06/2015 (32 bit modifications)
  4076                              <1> 	; 14/01/2014
  4077 00004084 31C0                <1> 	xor 	eax, eax
  4078 00004086 6648                <1> 	dec	ax ; 17/10/2015
  4079 00004088 A3[5C700000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4080                              <1> 	;;;
  4081                              <1> 	; 01/02/2022
  4082 0000408D FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4083 0000408F 39C2                <1> 	cmp	edx, eax
  4084                              <1> 	;cmp	dx, ax ; 0FFFFh
  4085 00004091 7521                <1> 	jne	short sysstty_18
  4086                              <1> 	; clear video page
  4087                              <1> 	; (CH must be 0)
  4088 00004093 08ED                <1> 	or	ch, ch
  4089 00004095 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4090 00004097 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4091 0000409A 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4092 0000409C 20C9                <1> 	and	cl, cl
  4093 0000409E 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4094 000040A0 0FB635[A5700000]    <1> 	movzx	esi, byte [u.uno]
  4095 000040A7 8A8E[B76D0000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4096 000040AD 80F907              <1> 	cmp	cl, 7
  4097 000040B0 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4098                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4099 000040B2 FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4100                              <1> sysstty_18:
  4101 000040B4 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4102                              <1> 	; cl = video page (tty) number		
  4103                              <1> 	;;;
  4104 000040B6 21DB                <1> 	and	ebx, ebx
  4105                              <1> 	;jnz	sysstty_6
  4106                              <1> 	; 01/02/2022
  4107 000040B8 7405                <1> 	jz	short sysstty_19
  4108 000040BA E9C2000000          <1> 	jmp	sysstty_6
  4109                              <1> sysstty_19:
  4110                              <1> 	; set console tty
  4111                              <1> 	; 29/10/2015
  4112                              <1> 	; 17/01/2014 
  4113 000040BF 80F909              <1> 	cmp	cl, 9
  4114 000040C2 7613                <1> 	jna	short sysstty_0
  4115                              <1> 	; 17/11/2015
  4116 000040C4 80F9FF              <1> 	cmp	cl, 0FFh
  4117 000040C7 7202                <1> 	jb	short sysstty_13
  4118 000040C9 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4119                              <1> sysstty_13:
  4120 000040CB 8A1D[A5700000]      <1> 	mov	bl, [u.uno] ; process number
  4121 000040D1 8A8B[B76D0000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4122                              <1> sysstty_0:
  4123                              <1> 	; 29/06/2015
  4124                              <1> 	;push	dx
  4125                              <1> 	;push	cx
  4126                              <1> 	; 01/02/2022
  4127 000040D7 52                  <1> 	push	edx
  4128 000040D8 51                  <1> 	push	ecx
  4129 000040D9 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4130 000040DB 88C8                <1> 	mov	al, cl
  4131 000040DD A2[5C700000]        <1> 	mov	[u.r0], al ; tyy number (0 to 9)
  4132 000040E2 E8F6190000          <1> 	call	ottyp
  4133                              <1> 	; 01/02/2022
  4134 000040E7 59                  <1> 	pop	ecx
  4135 000040E8 5A                  <1> 	pop	edx
  4136                              <1> 	;pop	cx
  4137                              <1> 	;pop	dx
  4138                              <1> 	;
  4139 000040E9 7220                <1> 	jc	short sysstty_pd_err
  4140                              <1> 	;
  4141                              <1> 	; 22/02/2022 (Bug!, BugFix)
  4142                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4143                              <1> 	;
  4144 000040EB 80F908              <1> 	cmp	cl, 8
  4145 000040EE 720C                <1> 	jb	short sysstty_2
  4146                              <1> 	;
  4147 000040F0 80FEFF              <1> 	cmp	dh, 0FFh
  4148 000040F3 7407                <1> 	je	short sysstty_2
  4149                              <1> 		; set communication parameters for serial ports
  4150                              <1> 
  4151                              <1> ; 01/02/2022
  4152                              <1> ;	; 29/10/2015
  4153                              <1> ;	mov	ah, dl ; communication parameters
  4154                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4155                              <1> ;		;			 THRE int + RDA int 
  4156                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4157                              <1> ;		;			 THRE int + RDA int 
  4158                              <1> ;	sub	al, al ; 0
  4159                              <1> ;	; 12/07/2014
  4160                              <1> ;	cmp	cl, 9
  4161                              <1> ;	jb	short sysstty_1
  4162                              <1> ;	inc	al
  4163                              <1> ;sysstty_1:
  4164                              <1> ;	; 01/02/2022
  4165                              <1> ;	push	ecx
  4166                              <1> ;	;push	cx
  4167                              <1> ;	; 29/06/2015	
  4168                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4169                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4170                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4171                              <1> ;	; 01/02/2022
  4172                              <1> ;	pop	ecx	
  4173                              <1> ;	;pop	cx
  4174                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4175                              <1> 
  4176                              <1> 	; 01/02/2022
  4177 000040F5 E832010000          <1> 	call	sysstty_scp
  4178 000040FA 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4179                              <1> 
  4180                              <1> sysstty_2:
  4181                              <1> 	; 17/01/2014
  4182 000040FC 20ED                <1> 	and	ch, ch 	; set cursor position 
  4183                              <1> 			; or comm. parameters ONLY
  4184 000040FE 7527                <1> 	jnz	short sysstty_3
  4185                              <1> 	; 01/02/2022
  4186 00004100 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4187 00004104 7214                <1> 	jb	short sysstty_20
  4188                              <1> 	; clear screen (video page)
  4189 00004106 E93D010000          <1> 	jmp	sysstty_14
  4190                              <1> 
  4191                              <1> sysstty_pd_err: ; 29/06/2015
  4192                              <1> 	; 'permission denied !' error
  4193 0000410B C705[AB700000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4193 00004113 0000                <1>
  4194 00004115 E9B9F9FFFF          <1> 	jmp	error
  4195                              <1> 
  4196                              <1> sysstty_20:
  4197 0000411A 0FB61D[A5700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4198 00004121 888B[B76D0000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4199                              <1> sysstty_3:
  4200                              <1> 	; 16/01/2014
  4201 00004127 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4202                              <1> 	; 17/11/2015
  4203 00004129 B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4204 0000412B 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4205                              <1> 	;jna	sysstty_9
  4206                              <1> 	; 01/02/2022
  4207 0000412D 7705                <1> 	ja	short sysstty_12
  4208 0000412F E9C7000000          <1> 	jmp	sysstty_9
  4209                              <1> 
  4210                              <1> sysstty_12:
  4211                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4212                              <1> 	; (Set specified serial port as console tty port)
  4213                              <1> 	; CH = character to be written
  4214                              <1> 	; 15/04/2014
  4215                              <1> 	; CH = 0 --> initialization only
  4216                              <1> 	; AL = character
  4217                              <1> 	; 26/06/2014
  4218 00004134 880D[AA700000]      <1> 	mov	[u.ttyn], cl
  4219                              <1> 	; 12/07/2014
  4220 0000413A 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4221                              <1> 	; 02/02/2022
  4222 0000413C FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4223 0000413E 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4224 00004140 FEC8                <1> 	dec	al  ; 1 -> 0	
  4225                              <1> 	;and	al, al
  4226 00004142 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4227                              <1>  	; 04/07/2014
  4228 00004144 E8EF1F0000          <1> 	call 	sndc
  4229                              <1> 	; 12/07/2014
  4230 00004149 EB0C                <1> 	jmp	short sysstty_5
  4231                              <1> 
  4232                              <1> sysstty_4:
  4233                              <1> 	; 12/07/2014
  4234                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4235 0000414B 88E0                <1> 	mov	al, ah ; 29/06/2015
  4236 0000414D 2C08                <1> 	sub	al, 8
  4237                              <1> 	; 27/06/2015
  4238 0000414F E832F4FFFF          <1> 	call	sp_status ; get serial port status
  4239                              <1> 	; AL = Line status, AH = Modem status
  4240                              <1> 	; 12/11/2015
  4241 00004154 3C80                <1> 	cmp	al, 80h
  4242 00004156 F5                  <1> 	cmc
  4243                              <1> sysstty_5:
  4244 00004157 66A3[5D700000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4245                              <1> 		; EAX bits 16-23 = modem status	
  4246 0000415D 9C                  <1> 	pushf
  4247 0000415E 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4248 00004160 A0[AA700000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4249 00004165 E8961A0000          <1> 	call	cttyp
  4250 0000416A 9D                  <1> 	popf
  4251                              <1> 	;jnc	sysret ; time out error 
  4252                              <1> 	; 01/02/2022
  4253 0000416B 7205                <1> 	jc	short sysstty_tmout_err
  4254 0000416D E981F9FFFF          <1> 	jmp	sysret
  4255                              <1> 
  4256                              <1> sysstty_tmout_err:
  4257 00004172 C705[AB700000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4257 0000417A 0000                <1>
  4258 0000417C E952F9FFFF          <1> 	jmp	error
  4259                              <1> 
  4260                              <1> sysstty_6:
  4261                              <1> 	;push	dx
  4262                              <1> 	;push	cx
  4263                              <1> 	; 01/02/2022
  4264 00004181 52                  <1> 	push	edx
  4265 00004182 51                  <1> 	push	ecx
  4266 00004183 891D[74700000]      <1> 	mov	[u.namep], ebx
  4267 00004189 E846080000          <1> 	call	namei
  4268                              <1> 	; 01/02/2022
  4269 0000418E 59                  <1> 	pop	ecx
  4270 0000418F 5A                  <1> 	pop	edx
  4271                              <1> 	;pop	cx
  4272                              <1> 	;pop	dx
  4273 00004190 725A                <1> 	jc	short sysstty_inv_dn
  4274                              <1> 	;
  4275 00004192 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4276 00004196 7754                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4277                              <1> 	;
  4278 00004198 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4279                              <1> 		       ; /dev/COM1, /dev/COM2
  4280 0000419A 7206                <1> 	jb	short sysstty_7
  4281 0000419C 2C0A                <1> 	sub	al, 10
  4282                              <1> 	; al = 0 to 9
  4283 0000419E 29DB                <1> 	sub	ebx, ebx ; 22/02/2022
  4284 000041A0 EB11                <1> 	jmp	short sysstty_8
  4285                              <1> 
  4286                              <1> sysstty_7:
  4287 000041A2 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4288 000041A4 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4289 000041A6 0FB61D[A5700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4290 000041AD 8A83[B76D0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4291                              <1> sysstty_8:
  4292                              <1> 	; 22/02/2022
  4293                              <1> 	; (ebx < 256)
  4294 000041B3 A2[5C700000]        <1> 	mov	[u.r0], al
  4295                              <1> 	; 01/02/2022
  4296                              <1> 	;push	dx
  4297                              <1> 	;push	ax
  4298                              <1> 	;push	cx
  4299 000041B8 52                  <1> 	push	edx
  4300 000041B9 50                  <1> 	push	eax
  4301 000041BA 51                  <1> 	push	ecx
  4302 000041BB E81D190000          <1> 	call	ottyp
  4303 000041C0 59                  <1> 	pop	ecx
  4304 000041C1 58                  <1> 	pop	eax
  4305 000041C2 5A                  <1> 	pop	edx
  4306                              <1> 	;pop	cx
  4307                              <1> 	;pop	ax
  4308                              <1> 	;pop	dx
  4309                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4310                              <1> 	; 01/02/2022
  4311 000041C3 7305                <1> 	jnc	short sysstty_21
  4312 000041C5 E941FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4313                              <1> sysstty_21:
  4314                              <1> 	; 29/10/2015
  4315 000041CA 86E9                <1> 	xchg 	ch, cl
  4316                              <1> 		; cl = character, ch = color code
  4317 000041CC 86C1                <1> 	xchg	al, cl
  4318                              <1> 		; al = character, cl = tty number
  4319 000041CE 80F907              <1> 	cmp	cl, 7
  4320                              <1> 	;ja	sysstty_12
  4321                              <1> 	; 01/02/2022
  4322 000041D1 7628                <1> 	jna	short sysstty_16
  4323                              <1> ;;
  4324 000041D3 80FEFF              <1> 	cmp	dh, 0FFh
  4325 000041D6 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4326                              <1> 
  4327                              <1> ; 01/02/2022
  4328                              <1> ;	; 29/10/2015
  4329                              <1> ;	mov	ah, dl ; communication parameters
  4330                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4331                              <1> ;		;			 THRE int + RDA int 
  4332                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4333                              <1> ;		;			 THRE int + RDA int 
  4334                              <1> ;	sub	al, al ; 0
  4335                              <1> ;	; 12/07/2014
  4336                              <1> ;	cmp	cl, 9
  4337                              <1> ;	jb	short sysstty_1
  4338                              <1> ;	inc	al
  4339                              <1> ;sysstty_1:
  4340                              <1> ;	; 01/02/2022
  4341                              <1> ;	push	ecx
  4342                              <1> ;	;push	cx
  4343                              <1> ;	; 29/06/2015	
  4344                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4345                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4346                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4347                              <1> ;	; 01/02/2022
  4348                              <1> ;	pop	ecx	
  4349                              <1> ;	;pop	cx
  4350                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4351                              <1> 
  4352                              <1> 	; 02/02/2022
  4353 000041D8 88C5                <1> 	mov	ch, al ; save char
  4354                              <1> 	; 01/02/2022
  4355 000041DA E84D000000          <1> 	call	sysstty_scp
  4356 000041DF 7291                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4357                              <1> 	; 02/02/2022
  4358 000041E1 88E8                <1> 	mov	al, ch ; restore char
  4359                              <1> sysstty_22:
  4360                              <1> 	; 01/02/2022
  4361 000041E3 08ED                <1> 	or	ch, ch
  4362 000041E5 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4363                              <1> 	; send char to (serial port) terminal
  4364                              <1> 	; al = character
  4365                              <1> 	; cl = tty number (8 or 9)
  4366 000041E7 E948FFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4367                              <1> 
  4368                              <1> sysstty_inv_dn: 
  4369                              <1> 	; 27/06/2015
  4370                              <1> 	; Invalid device name (not a tty) ! error
  4371                              <1> 	; (Device is not a tty or device name not found)
  4372 000041EC C705[AB700000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4372 000041F4 0000                <1>
  4373 000041F6 E9D8F8FFFF          <1> 	jmp	error 
  4374                              <1> 
  4375                              <1> sysstty_16:
  4376                              <1> 	; 22/02/2022
  4377                              <1> 	; 16/01/2014
  4378                              <1> 	;xor	bh, bh
  4379                              <1> sysstty_9: 	; tty 0 to tty 7
  4380                              <1> 	; al = character
  4381                              <1> 	; ch = color/attribute ; 01/02/2022
  4382                              <1> 	;
  4383                              <1>  	; 22/02/2022 (BugFix)
  4384                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4385 000041FB 29DB                <1> 	sub	ebx, ebx ; *
  4386 000041FD 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4387                              <1> 	;
  4388 000041FF 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4389 00004202 7409                <1> 	je	short sysstty_10
  4390                              <1> 	; 02/02/2022
  4391 00004204 51                  <1> 	push	ecx
  4392 00004205 50                  <1> 	push	eax
  4393                              <1> 	;push	cx
  4394                              <1> 	;push	ax	
  4395                              <1> 	; 22/02/2022	
  4396                              <1> 	;;movzx	ebx, cl ; *
  4397                              <1> 	;mov	bl, cl ; (tty number = video page number)
  4398 00004206 E8D9D2FFFF          <1> 	call	set_cpos
  4399                              <1> 	;pop	ax
  4400                              <1> 	;pop	cx
  4401                              <1> 	; 02/02/2022
  4402 0000420B 58                  <1> 	pop	eax
  4403 0000420C 59                  <1> 	pop	ecx
  4404                              <1> sysstty_10: 
  4405                              <1> 	; 29/10/2015
  4406 0000420D 08C0                <1> 	or	al, al ; character
  4407 0000420F 740D                <1> 	jz      short sysstty_11 ; al = 0
  4408                              <1> 	; 17/11/2015
  4409 00004211 3CFF                <1> 	cmp	al, 0FFh
  4410 00004213 7309                <1> 	jnb	short sysstty_11
  4411                              <1> 		; ch > 0 and ch < FFh
  4412                              <1> 	; write a character at current cursor position
  4413 00004215 88EC                <1> 	mov	ah, ch ; color/attribute
  4414                              <1> 	; 12/07/2014
  4415                              <1> 	;push	cx
  4416                              <1> 	; 02/02/2022
  4417 00004217 51                  <1> 	push	ecx
  4418 00004218 E8AFD3FFFF          <1> 	call	write_c_current
  4419                              <1> 	;pop	cx
  4420                              <1> 	; 02/02/2022
  4421 0000421D 59                  <1> 	pop	ecx
  4422                              <1> sysstty_11:
  4423                              <1> 	; 14/01/2014
  4424 0000421E 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4425                              <1> 	; 18/01/2014
  4426                              <1> 	;movzx	eax, cl ; 27/06/2015
  4427 00004220 88C8                <1> 	mov	al, cl
  4428 00004222 E8D9190000          <1> 	call	cttyp
  4429 00004227 E9C7F8FFFF          <1> 	jmp	sysret
  4430                              <1> 
  4431                              <1> sysstty_scp:
  4432                              <1> 	; 02/02/2022
  4433                              <1> 	; set communication parameters (for COM1 or COM2)
  4434                              <1> 	; 01/02/2022
  4435                              <1> 	;
  4436                              <1> 	; 29/10/2015
  4437 0000422C 88D4                <1> 	mov	ah, dl ; communication parameters
  4438                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4439                              <1> 		;			 THRE int + RDA int 
  4440                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4441                              <1> 		;			 THRE int + RDA int 
  4442 0000422E 28C0                <1> 	sub	al, al ; 0
  4443                              <1> 	; 12/07/2014
  4444 00004230 80F909              <1> 	cmp	cl, 9
  4445 00004233 7202                <1> 	jb	short sysstty_1
  4446 00004235 FEC0                <1> 	inc	al
  4447                              <1> sysstty_1:
  4448                              <1> 	; 02/02/2022
  4449 00004237 52                  <1> 	push	edx
  4450                              <1> 	; 01/02/2022
  4451 00004238 51                  <1> 	push	ecx
  4452                              <1> 	;push	cx
  4453                              <1> 	; 29/06/2015	
  4454 00004239 E850F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4455 0000423E 66890D[5D700000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4456                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4457                              <1> 	; 01/02/2022
  4458 00004245 59                  <1> 	pop	ecx	
  4459                              <1> 	;pop	cx
  4460 00004246 5A                  <1> 	pop	edx ; 02/02/2022
  4461                              <1> 	; 01/02/2022
  4462                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4463 00004247 C3                  <1> 	retn
  4464                              <1> 
  4465                              <1> sysstty_14:
  4466                              <1> 	; 23/02/2022
  4467                              <1> 	; 02/02/2022
  4468                              <1> 	; ch = 0
  4469                              <1> 	; cl = video page
  4470                              <1> 	;
  4471                              <1> 	; dx = 0FFFFh
  4472                              <1> 	; clear screen (video page)
  4473                              <1> 	;
  4474                              <1> 
  4475                              <1> 	; 02/02/2022
  4476                              <1> 	; clear screen
  4477                              <1> 	;
  4478                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4479                              <1> 
  4480                              <1> 	; 23/02/2022
  4481 00004248 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4482                              <1> 
  4483                              <1> 	; clear video page
  4484 0000424A E810000000          <1> 	call	wttyc ; 23/02/2022
  4485                              <1> 
  4486                              <1> 	; 23/02/2022
  4487 0000424F 88D8                <1> 	mov	al, bl
  4488 00004251 8A25[A5700000]      <1> 	mov	ah, [u.uno]
  4489 00004257 66A3[5C700000]      <1> 	mov	[u.r0], ax
  4490 0000425D EBBF                <1> 	jmp	short sysstty_11
  4491                              <1> 
  4492                              <1> vp_clr:	; 27/02/2022
  4493                              <1> wttyc:
  4494                              <1> 	; 23/02/2022
  4495                              <1> 	; (clear video page)
  4496                              <1> 	; INPUT:
  4497                              <1> 	;  bl = video page (0 to 7)
  4498                              <1> 	;
  4499                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4500                              <1> 
  4501                              <1> 	;xor	dx, dx ; column 0, row 0
  4502                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4503                              <1> 	;
  4504                              <1> ;	movzx	ebx, cl
  4505                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4506                              <1> 
  4507                              <1> ;	shl 	bl, 1 
  4508                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4509                              <1> ;		; AL = lock value (0 or process number)
  4510                              <1> ;	or	al, al
  4511                              <1> ;	jz	short @f
  4512                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4513                              <1> ;	jne	short sysstty_15
  4514                              <1> ;		; only the owner can clear its video page
  4515                              <1> ;	xor	al, al ; 0
  4516                              <1> ;@@:
  4517                              <1> ;	;mov	bl, cl		
  4518                              <1> ;	shr	bl, 1 
  4519                              <1> 
  4520 0000425F 30C0                <1> 	xor	al, al	; 0
  4521 00004261 B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4522                              <1> 
  4523                              <1> 	; scroll_up input:
  4524                              <1> 	;
  4525                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4526                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4527                              <1> 	; ah = attribute to be used on blanked line
  4528                              <1> 	; bl = video page number (0 to 7)
  4529                              <1> 
  4530 00004263 E802D3FFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4531                              <1> 
  4532                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4533                              <1> 
  4534                              <1> 	; bl = video page number (0 to 7)
  4535                              <1> 	;xor	dx, dx ; column 0, row 0
  4536                              <1> 	; 02/02/2022
  4537 00004268 31D2                <1> 	xor	edx, edx
  4538                              <1> 	; 23/02/2022
  4539                              <1> 	;call	set_cpos
  4540                              <1> 	;retn
  4541 0000426A E975D2FFFF          <1> 	jmp	set_cpos
  4542                              <1> 
  4543                              <1> 	;mov	al, bl
  4544                              <1> 	;mov	ah, [u.uno]
  4545                              <1> 	;mov	[u.r0], ax
  4546                              <1> 	;jmp	short sysstty_11
  4547                              <1> 
  4548                              <1> ;sysstty_15:
  4549                              <1> ;	; 30/01/2022
  4550                              <1> ;	; permission (denied) error
  4551                              <1> ;	;xor	dl, dl ; sysstty call sign
  4552                              <1> ;	mov	al, cl
  4553                              <1> ;	sub	ah, ah ; 0
  4554                              <1> ;	call	cttyp
  4555                              <1> ;	jmp	error
  4556                              <1> 
  4557                              <1> ; Original UNIX v1 'sysstty' routine:
  4558                              <1> ; gtty:
  4559                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4560                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4561                              <1> 	; 		/ r2 has source
  4562                              <1>         ;mov    r2,-(sp)
  4563                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4564                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4565                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4566                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4567                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4568                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4569                              <1>         ;       br .+4 / list empty, skip branch
  4570                              <1>         ;br     1b / get another character until list is empty
  4571                              <1>         ;mov    0b,r1 / move cc offset to r1
  4572                              <1>         ;inc    r1 / bump it for output clist
  4573                              <1>         ;tstb   cc(r1) / is it 0
  4574                              <1>         ;beq    1f / yes, no characters to output
  4575                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4576                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4577                              <1>         ;br     1b / try to calm it down again
  4578                              <1> ;1:
  4579                              <1>         ;mov    (sp)+,r1
  4580                              <1>         ;mov    (sp)+,r2 / restore registers
  4581                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4582                              <1>         ;beq    1f / if 0, 1f
  4583                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4584                              <1>         ;                   / control status register
  4585                              <1> ;1:
  4586                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4587                              <1>         ;beq    1f / if 0 1f
  4588                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4589                              <1> 	;		    / control status reg
  4590                              <1> ;1:
  4591                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4592                              <1>         ;jmp	sysret2 / return to user
  4593                              <1> 
  4594                              <1> sysgtty: ; < get tty status >
  4595                              <1> 	; 22/02/2022
  4596                              <1> 	; 01/02/2022
  4597                              <1> 	; 23/11/2015
  4598                              <1> 	; 29/10/2015
  4599                              <1> 	; 17/10/2015
  4600                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4601                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4602                              <1> 	;
  4603                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4604                              <1> 	; It stores in the three words addressed by it's argument
  4605                              <1> 	; the status of the typewriter whose file descriptor
  4606                              <1> 	; in (u.r0).
  4607                              <1> 	;
  4608                              <1> 	; Calling sequence:
  4609                              <1> 	;	sysgtty; arg
  4610                              <1> 	; Arguments:
  4611                              <1> 	;	arg - address of 3 words destination of the status
  4612                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4613                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4614                              <1> 	; ...............................................................
  4615                              <1> 	;	
  4616                              <1> 	; Retro UNIX 8086 v1 modification: 
  4617                              <1> 	;	'sysgtty' system call will return status of tty
  4618                              <1> 	;	(keyboard, serial port and video page status)
  4619                              <1> 	;	 in following manner:
  4620                              <1> 	;
  4621                              <1> 	; Inputs:
  4622                              <1> 	;	BX = 0 --> means 
  4623                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4624                              <1> 	;	                 for (current) process
  4625                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4626                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4627                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4628                              <1> 	;	     CH > 0 -->	tty number + 1
  4629                              <1> 	;
  4630                              <1> 	;	BX > 0 --> points to name of tty
  4631                              <1> 	;	     CL = 0 --> return keyboard status
  4632                              <1> 	;	     CL = 1 --> return video page status
  4633                              <1> 	;	     CH = undefined		 
  4634                              <1> 	;
  4635                              <1> 	; Outputs:
  4636                              <1> 	;	cf = 0 ->
  4637                              <1> 	;
  4638                              <1> 	;	     AL = tty number from 0 to 9
  4639                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4640                              <1> 	;	     AH = 0 if the tty is free/unused
  4641                              <1> 	;	     AH = the process number of the caller 
  4642                              <1>  	;	     AH = FFh if the tty is locked by another process
  4643                              <1> 	;
  4644                              <1> 	;	  (if calling is for serial port status)
  4645                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4646                              <1> 	;		  (BH = modem status, BL = Line status)
  4647                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4648                              <1> 	;	     CX = 0 (if data is not ready or undefined)
  4649                              <1> 	;
  4650                              <1> 	;	  (if calling is for keyboard status)
  4651                              <1> 	;	     BX = current character in tty/keyboard buffer
  4652                              <1> 	;		  (BH = scan code, BL = ascii code)
  4653                              <1> 	;		  (BX=0 if there is not a waiting character)
  4654                              <1> 	;	     CX  is undefined
  4655                              <1> 	;
  4656                              <1> 	;	  (if calling is for video page status)	
  4657                              <1> 	;	     BX = cursor position on the video page
  4658                              <1> 	;		  if tty number < 8
  4659                              <1> 	;		  (BH = row, BL = column)
  4660                              <1> 	;	     CX = current character (in cursor position)
  4661                              <1> 	;		  on the video page of the tty 
  4662                              <1> 	;		  if tty number < 8
  4663                              <1> 	;		  (CH = color, CL = character)
  4664                              <1> 	;	
  4665                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4666                              <1> 	;
  4667                              <1> 	;	     AH = FFh if the caller is not owner of
  4668                              <1> 	;		  specified tty or console tty
  4669                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4670                              <1> 	;	     BX, CX are undefined if cf = 1
  4671                              <1> 	;
  4672                              <1> 	;	  (If tty number is 8 or 9)
  4673                              <1> 	;	     AL = tty number 
  4674                              <1> 	;	     AH = the process number of the caller 
  4675                              <1> 	;	     BX = serial port status
  4676                              <1> 	;  		 (BH = modem status, BL = Line status)
  4677                              <1> 	;	     CX = 0
  4678                              <1> 	;
  4679                              <1> 		
  4680                              <1> gtty:   ; get (requested) tty number
  4681                              <1> 	; 22/02/2022
  4682                              <1> 	; 01/02/2022
  4683                              <1> 	; 17/10/2015
  4684                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4685                              <1> 	; 30/05/2013 - 12/07/2014
  4686                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4687                              <1> 	;
  4688                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4689                              <1> 	;
  4690                              <1> 	; 28/06/2015 (32 bit modifications)
  4691                              <1> 	; 16/01/2014
  4692 0000426F 31C0                <1> 	xor 	eax, eax
  4693 00004271 6648                <1> 	dec	ax ; 17/10/2015
  4694 00004273 A3[5C700000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4695 00004278 80F901              <1> 	cmp	cl, 1
  4696 0000427B 760F                <1> 	jna	short sysgtty_0
  4697                              <1> sysgtty_invp:
  4698                              <1> 	; 28/06/2015
  4699 0000427D C705[AB700000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4699 00004285 0000                <1>
  4700 00004287 E947F8FFFF          <1> 	jmp	error
  4701                              <1> sysgtty_0:	
  4702 0000428C 21DB                <1> 	and	ebx, ebx
  4703 0000428E 742E                <1> 	jz	short sysgtty_1
  4704                              <1> 	;
  4705 00004290 891D[74700000]      <1> 	mov	[u.namep], ebx
  4706                              <1> 	;push	cx ; 23/11/2015
  4707                              <1> 	; 01/02/2022
  4708 00004296 51                  <1> 	push	ecx
  4709 00004297 E838070000          <1> 	call	namei
  4710                              <1> 	; 01/02/2022
  4711 0000429C 59                  <1> 	pop	ecx
  4712                              <1> 	;pop	cx ; 23/11/2015
  4713 0000429D 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4714                              <1> 	;
  4715 0000429F 6683F801            <1> 	cmp	ax, 1
  4716 000042A3 7622                <1> 	jna	short sysgtty_2
  4717                              <1> 	; 01/02/2022
  4718 000042A5 20E4                <1> 	and	ah, ah
  4719 000042A7 7506                <1> 	jnz	short sysgtty_inv_dn
  4720                              <1> 	;sub	ax, 10
  4721 000042A9 2C0A                <1> 	sub	al, 10
  4722 000042AB 3C09                <1> 	cmp	al, 9
  4723                              <1> 	;cmp	ax, 9
  4724                              <1> 	;ja	short sysgtty_inv_dn
  4725                              <1> 	;mov	ch, al
  4726                              <1> 	;jmp	short sysgtty_4
  4727                              <1> 	; 23/11/2015
  4728 000042AD 7629                <1> 	jna	short sysgtty_4
  4729                              <1> sysgtty_inv_dn: 
  4730                              <1> 	; 28/06/2015
  4731                              <1> 	; Invalid device name (not a tty) ! error
  4732                              <1> 	; (Device is not a tty or device name not found)
  4733 000042AF C705[AB700000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4733 000042B7 0000                <1>
  4734 000042B9 E915F8FFFF          <1> 	jmp	error 
  4735                              <1> sysgtty_1:
  4736                              <1> 	; 16/01/2014
  4737 000042BE 80FD0A              <1> 	cmp	ch, 10
  4738 000042C1 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4739 000042C3 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4740 000042C5 790F                <1> 	jns	short sysgtty_3 ; not negative
  4741                              <1> 	;
  4742                              <1> sysgtty_2:
  4743                              <1> 	; get tty number of console tty
  4744 000042C7 8A25[A5700000]      <1> 	mov	ah, [u.uno]
  4745                              <1>  	; 28/06/2015
  4746 000042CD 0FB6DC              <1> 	movzx 	ebx, ah
  4747 000042D0 8AAB[B76D0000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4748                              <1> sysgtty_3:
  4749 000042D6 88E8                <1> 	mov	al, ch
  4750                              <1> sysgtty_4:
  4751 000042D8 A2[5C700000]        <1> 	mov	[u.r0], al
  4752                              <1>  	; 28/06/2015
  4753                              <1> 	;cmp	al, 9
  4754                              <1> 	;ja	short sysgtty_invp
  4755 000042DD 8B2D[58700000]      <1> 	mov	ebp, [u.usp]
  4756                              <1> 	; 23/11/2015
  4757 000042E3 20C9                <1> 	and	cl, cl
  4758 000042E5 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4759 000042E7 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4760 000042E9 722E                <1> 	jb	short sysgtty_6 ; video page status
  4761                              <1> 	; serial port status
  4762                              <1> 	; 12/07/2014
  4763                              <1> 	;mov	dx, 0
  4764                              <1> 	;je	short sysgtty_5
  4765                              <1> 	;inc	dl
  4766                              <1> ;sysgtty_5:
  4767                              <1> 	; 28/06/2015
  4768 000042EB 2C08                <1> 	sub	al, 8
  4769 000042ED E894F2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4770                              <1> 	; AL = Line status, AH = Modem status
  4771 000042F2 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4772 000042F6 8A25[A5700000]      <1> 	mov	ah, [u.uno]
  4773 000042FC 8825[5D700000]      <1>         mov     [u.r0+1], ah
  4774 00004302 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)	
  4775                              <1> 				; (in ECX)
  4776 00004308 A880                <1> 	test	al, 80h
  4777 0000430A 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4778 0000430C A801                <1> 	test	al, 1
  4779                              <1> 	;jz	sysret
  4780 0000430E 7404                <1> 	jz	short sysgtty_10 ; 22/02/2022
  4781 00004310 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)	
  4782                              <1> sysgtty_10:
  4783 00004314 E9DAF7FFFF          <1> 	jmp	sysret
  4784                              <1> sysgtty_6:
  4785 00004319 A2[AA700000]        <1> 	mov	[u.ttyn], al ; tty number
  4786                              <1> 	;movzx	ebx, al
  4787 0000431E 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4788 00004320 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4789                              <1> 	; 22/04/2014 - 29/06/2015
  4790 00004322 81C3[E46C0000]      <1>         add     ebx, ttyl
  4791 00004328 8A23                <1>  	mov	ah, [ebx]
  4792 0000432A 3A25[A5700000]      <1> 	cmp	ah, [u.uno]
  4793 00004330 7404                <1> 	je	short sysgtty_7
  4794 00004332 20E4                <1> 	and	ah, ah
  4795                              <1> 	;jz	short sysgtty_7
  4796 00004334 7506                <1> 	jnz	short sysgtty_8
  4797                              <1> 	;mov	ah, 0FFh
  4798                              <1> sysgtty_7:
  4799 00004336 8825[5D700000]      <1>         mov     [u.r0+1], ah
  4800                              <1> sysgtty_8:
  4801 0000433C 08C9                <1> 	or	cl, cl
  4802 0000433E 7510                <1> 	jnz	short sysgtty_9
  4803 00004340 B001                <1> 	mov	al, 1  ; test a key is available
  4804 00004342 E8741D0000          <1> 	call	getc
  4805 00004347 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4806 0000434B E9A3F7FFFF          <1> 	jmp	sysret
  4807                              <1> sysgtty_9:
  4808 00004350 8A1D[AA700000]      <1> 	mov	bl, [u.ttyn]
  4809                              <1> 	; bl = video page number
  4810 00004356 E8D11E0000          <1> 	call 	get_cpos
  4811                              <1> 	; dx = cursor position
  4812 0000435B 66895510            <1> 	mov	[ebp+16], dx ; bx
  4813                              <1> 	;mov	bl, [u.ttyn]
  4814                              <1> 	; bl = video page number
  4815 0000435F E8D91E0000          <1> 	call	read_ac_current
  4816                              <1> 	; ax = character and attribute/color
  4817 00004364 66894518            <1> 	mov	[ebp+24], ax ; cx
  4818 00004368 E986F7FFFF          <1> 	jmp	sysret
  4819                              <1> sysgtty_dnr_err:
  4820                              <1> 	; 'device not responding !' error	
  4821                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4822 0000436D C705[AB700000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ;  25
  4822 00004375 0000                <1>
  4823 00004377 E957F7FFFF          <1> 	jmp	error	
  4824                              <1> 
  4825                              <1> ; Original UNIX v1 'sysgtty' routine:
  4826                              <1> ; sysgtty:
  4827                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4828                              <1> 	;	       / r2 has destination
  4829                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4830                              <1> 	;                     / in 1st word of dest
  4831                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4832                              <1> 	;                     / in 2nd word of dest
  4833                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4834                              <1>         ;jmp    sysret2 / return to user
  4835                              <1> 	
  4836                              <1> ; Original UNIX v1 'gtty' routine:
  4837                              <1> ; gtty:
  4838                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4839                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4840                              <1>         ;jsr    r0,getf / get the i-number of the file
  4841                              <1>         ;tst    r1 / is it open for reading
  4842                              <1>         ;bgt    1f / yes
  4843                              <1>         ;neg    r1 / no, i-number is negative, 
  4844                              <1> 	;          / so make it positive
  4845                              <1> ;1:
  4846                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4847                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4848                              <1>         ;bhis   error9 / no, error
  4849                              <1>         ;asl    r1 / 0%2
  4850                              <1>         ;asl    r1 / 0%4 / yes
  4851                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4852                              <1> 	;	       ; / tty block
  4853                              <1>         ;mov    u.off,r2 / put argument in r2
  4854                              <1>         ;rts    r0 / return
  2049                                  %include 'u2.s'        ; 11/05/2015
  2050                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYS2.INC
  2051                              <1> ; Last Modification: 15/05/2022
  2052                              <1> ; ----------------------------------------------------------------------------
  2053                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2054                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2055                              <1> ;
  2056                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2057                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2058                              <1> ; <Bell Laboratories (17/3/1972)>
  2059                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2060                              <1> ;
  2061                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2062                              <1> ;
  2063                              <1> ; ****************************************************************************
  2064                              <1> ; 03/01/2016
  2065                              <1> 
  2066                              <1> syslink:
  2067                              <1> 	; 03/02/2022
  2068                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2069                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2070                              <1> 	;
  2071                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2072                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2073                              <1> 	; given to the entry that will go in the current directory.
  2074                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2075                              <1> 	; in the name 2 entry of current directory is the same
  2076                              <1> 	; i-number for the name 1 file.
  2077                              <1> 	;
  2078                              <1> 	; Calling sequence:
  2079                              <1> 	;	syslink; name 1; name 2
  2080                              <1> 	; Arguments:
  2081                              <1> 	;	name 1 - file name to which link will be created.
  2082                              <1> 	;	name 2 - name of entry in current directory that
  2083                              <1> 	;		 links to name 1.
  2084                              <1> 	; Inputs: -
  2085                              <1> 	; Outputs: -
  2086                              <1> 	; ...............................................................
  2087                              <1> 	;	
  2088                              <1> 	; Retro UNIX 8086 v1 modification: 
  2089                              <1> 	;       'syslink' system call has two arguments; so,
  2090                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2091                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2092                              <1> 	;
  2093                              <1> 		; / name1, name2
  2094                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2095 0000437C 891D[74700000]      <1> 	mov	[u.namep], ebx
  2096 00004382 51                  <1> 	push	ecx
  2097 00004383 E84C060000          <1> 	call	namei
  2098                              <1> 		; jsr r0,namei / find the i-number associated with
  2099                              <1> 			     ; / the 1st path name
  2100                              <1>      	;;and	ax, ax
  2101                              <1> 	;;jz	error ; File not found
  2102                              <1> 	;jc	error 
  2103                              <1> 		; br error9 / cannot be found
  2104 00004388 730F                <1> 	jnc	short syslink0
  2105                              <1> 	;pop 	ecx
  2106                              <1> 	; 'file not found !' error
  2107 0000438A C705[AB700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2107 00004392 0000                <1>
  2108 00004394 E93AF7FFFF          <1> 	jmp	error
  2109                              <1> syslink0:
  2110 00004399 E84B0E0000          <1> 	call	iget
  2111                              <1> 		; jsr r0,iget / get the i-node into core
  2112 0000439E 8F05[74700000]      <1> 	pop	dword [u.namep] ; ecx
  2113                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2114                              <1> 	; 03/02/2022
  2115 000043A4 50                  <1> 	push	eax
  2116                              <1> 	;push	ax
  2117                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2118                              <1> 			    ; / (a link to this file is to be created)
  2119 000043A5 66FF35[40700000]    <1> 	push	word [cdev]
  2120                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2121 000043AC E852000000          <1> 	call	isdir
  2122                              <1> 		; jsr r0,isdir / is it a directory
  2123 000043B1 E81E060000          <1> 	call	namei
  2124                              <1> 		; jsr r0,namei / no, get i-number of name2
  2125                              <1> 	;jnc	error
  2126                              <1> 		; br .+4   / not found 
  2127                              <1> 			 ; / so r1 = i-number of current directory
  2128                              <1> 			 ; / ii = i-number of current directory
  2129                              <1> 		; br error9 / file already exists., error
  2130 000043B6 720F                <1> 	jc	short syslink1
  2131                              <1> 	; pop ax
  2132                              <1> 	; pop ax
  2133                              <1> 	; 'file exists !' error
  2134 000043B8 C705[AB700000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2134 000043C0 0000                <1>
  2135 000043C2 E90CF7FFFF          <1> 	jmp	error
  2136                              <1> syslink1:
  2137 000043C7 6659                <1> 	pop	cx
  2138                              <1> 	;cmp	cx, [cdev]
  2139 000043C9 3A0D[40700000]      <1> 	cmp	cl, [cdev]
  2140                              <1> 	;jne	error
  2141                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2142                              <1> 			       ; / end of current directory
  2143                              <1> 	        ; bne error9
  2144 000043CF 740F                <1> 	je	short syslink2
  2145                              <1> 	; 'not same drive !' error
  2146 000043D1 C705[AB700000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2146 000043D9 0000                <1>
  2147 000043DB E9F3F6FFFF          <1> 	jmp	error
  2148                              <1> syslink2:
  2149                              <1> 	;pop	ax
  2150                              <1> 	;push	ax
  2151                              <1> 	; 03/02/2022
  2152                              <1> 	;mov	eax, [esp]
  2153 000043E0 58                  <1> 	pop	eax
  2154 000043E1 50                  <1> 	push	eax
  2155 000043E2 66A3[8E700000]      <1> 	mov	[u.dirbuf], ax
  2156                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2157 000043E8 E89E000000          <1> 	call	mkdir
  2158                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2159                              <1> 		 	     ; / in current directory
  2160                              <1> 	; 03/02/2022
  2161 000043ED 58                  <1> 	pop	eax
  2162                              <1> 	;pop	ax
  2163                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2164 000043EE E8F60D0000          <1> 	call	iget
  2165                              <1> 		; jsr r0,iget / get i-node into core
  2166 000043F3 FE05[5A6D0000]      <1> 	inc	byte [i.nlks]
  2167                              <1> 		; incb i.nlks / add 1 to its number of links
  2168 000043F9 E8F50E0000          <1> 	call	setimod
  2169                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2170 000043FE E9F0F6FFFF          <1> 	jmp	sysret
  2171                              <1> 
  2172                              <1> isdir:
  2173                              <1> 	; 03/02/2022
  2174                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2175                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2176                              <1> 	;
  2177                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2178                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2179                              <1> 	;  called by syslink and sysunlink to make sure directories
  2180                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2181                              <1> 	; 'isdir' does not bother checking. The current i-node
  2182                              <1> 	;  is not disturbed.			
  2183                              <1> 	;		
  2184                              <1> 	; INPUTS ->
  2185                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2186                              <1> 	;    u.uid - user id
  2187                              <1> 	; OUTPUTS ->
  2188                              <1> 	;    r1 - contains current i-number upon exit
  2189                              <1> 	;    	 (current i-node back in core) 
  2190                              <1> 	;	
  2191                              <1> 	; ((AX = R1))
  2192                              <1> 	;
  2193                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2194                              <1> 	;
  2195                              <1> 
  2196                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2197                              <1> 	; / there is an error unless super user made the call
  2198                              <1> 	
  2199 00004403 803D[A2700000]00    <1> 	cmp	byte [u.uid], 0 
  2200                              <1> 		; tstb u.uid / super user
  2201 0000440A 762B                <1> 	jna	short isdir1
  2202                              <1> 		; beq 1f / yes, don't care
  2203 0000440C 66FF35[3C700000]    <1> 	push	word [ii]
  2204                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2205 00004413 E8D10D0000          <1> 	call	iget
  2206                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2207                              <1> 	; 03/02/2022
  2208 00004418 F605[596D0000]40    <1> 	test	byte [i.flgs+1], 40h
  2209                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2210                              <1> 		; bit $40000,i.flgs / is it a directory
  2211                              <1> 	;jnz	error
  2212                              <1> 		; bne error9 / yes, error
  2213 0000441F 740F                <1> 	jz	short isdir0
  2214 00004421 C705[AB700000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2214 00004429 0000                <1>
  2215                              <1> 				; 'permission denied !' error
  2216                              <1> 	;pop	ax
  2217 0000442B E9A3F6FFFF          <1> 	jmp	error	
  2218                              <1> isdir0:	
  2219 00004430 6658                <1> 	pop	ax
  2220                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2221 00004432 E8B20D0000          <1> 	call	iget
  2222                              <1> 		; jsr r0,iget / get it back in
  2223                              <1> isdir1: ; 1:
  2224 00004437 C3                  <1> 	retn
  2225                              <1> 		; rts r0
  2226                              <1> 
  2227                              <1> sysunlink:
  2228                              <1> 	; 03/02/2022
  2229                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2230                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2231                              <1> 	;
  2232                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2233                              <1> 	; name from its directory. If this entry was the last link
  2234                              <1> 	; to the file, the contents of the file are freed and the
  2235                              <1> 	; file is destroyed. If, however, the file was open in any
  2236                              <1> 	; process, the actual destruction is delayed until it is 
  2237                              <1> 	; closed, even though the directory entry has disappeared.
  2238                              <1> 	; 
  2239                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2240                              <1> 	; does not exist or that its directory can not be written.
  2241                              <1> 	; Write permission is not required on the file itself.
  2242                              <1> 	; It is also illegal to unlink a directory (except for
  2243                              <1> 	; the superuser).
  2244                              <1> 	;
  2245                              <1> 	; Calling sequence:
  2246                              <1> 	;	sysunlink; name
  2247                              <1> 	; Arguments:
  2248                              <1> 	;	name - name of directory entry to be removed 
  2249                              <1> 	; Inputs: -
  2250                              <1> 	; Outputs: -
  2251                              <1> 	; ...............................................................
  2252                              <1> 	;				
  2253                              <1> 	; Retro UNIX 8086 v1 modification:
  2254                              <1> 	;	 The user/application program puts address of the name
  2255                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2256                              <1> 
  2257                              <1> 	; / name - remove link name
  2258 00004438 891D[74700000]      <1> 	mov	[u.namep], ebx
  2259                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2260 0000443E E891050000          <1> 	call	namei
  2261                              <1> 		; jsr r0,namei / find the i-number associated 
  2262                              <1> 			     ; / with the path name
  2263                              <1> 	;jc	error
  2264                              <1> 		; br error9 / not found
  2265 00004443 730F                <1> 	jnc	short sysunlink1
  2266                              <1> 	; 'file not found !' error
  2267 00004445 C705[AB700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2267 0000444D 0000                <1>
  2268 0000444F E97FF6FFFF          <1> 	jmp	error
  2269                              <1> sysunlink1:
  2270                              <1> 	; 03/02/2022
  2271 00004454 50                  <1> 	push	eax
  2272                              <1> 	;push	ax
  2273                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2274 00004455 E8A9FFFFFF          <1> 	call	isdir
  2275                              <1> 		; jsr r0,isdir / is it a directory
  2276                              <1> 	;xor 	ax, ax
  2277                              <1> 	; 03/02/2022
  2278 0000445A 31C0                <1> 	xor	eax, eax
  2279 0000445C 66A3[8E700000]      <1> 	mov	[u.dirbuf], ax ; 0
  2280                              <1> 		; clr u.dirbuf / no, clear the location that will
  2281                              <1> 			   ; / get written into the i-number portion
  2282                              <1> 			 ; / of the entry
  2283 00004462 832D[78700000]0A    <1> 	sub	dword [u.off], 10
  2284                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2285 00004469 E865000000          <1> 	call	wdir
  2286                              <1> 		; jsr r0,wdir / free the directory entry
  2287                              <1> 	; 03/02/2022
  2288 0000446E 58                  <1> 	pop	eax
  2289                              <1> 	;pop	ax
  2290                              <1> 		; mov (sp)+,r1 / get i-number back
  2291 0000446F E8750D0000          <1> 	call	iget
  2292                              <1> 		; jsr r0,iget / get i-node
  2293 00004474 E87A0E0000          <1> 	call	setimod
  2294                              <1> 		; jsr r0,setimod / set modified flag
  2295 00004479 FE0D[5A6D0000]      <1> 	dec	byte [i.nlks]
  2296                              <1> 		; decb i.nlks / decrement the number of links
  2297                              <1> 	;jnz	sysret
  2298                              <1> 		; bgt sysret9 / if this was not the last link
  2299                              <1> 			    ; / to file return
  2300                              <1> 	; 03/02/2022
  2301 0000447F 7505                <1> 	jnz	short sysunlink2
  2302                              <1> 	; AX = r1 = i-number
  2303 00004481 E8B8090000          <1> 	call	anyi
  2304                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2305                              <1> 			 ; / Then free contents of file and destroy it.
  2306                              <1> sysunlink2:
  2307 00004486 E968F6FFFF          <1> 	jmp	sysret
  2308                              <1> 		; br sysret9
  2309                              <1> 
  2310                              <1> mkdir:
  2311                              <1> 	; 03/02/2022
  2312                              <1> 	; 12/10/2015
  2313                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2314                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2315                              <1> 	;
  2316                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2317                              <1> 	; by u.namep into the current directory.
  2318                              <1> 	;
  2319                              <1> 	; INPUTS ->
  2320                              <1> 	;    u.namep - points to a file name 
  2321                              <1> 	;	           that is about to be a directory entry.
  2322                              <1> 	;    ii - current directory's i-number.	
  2323                              <1> 	; OUTPUTS ->
  2324                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2325                              <1> 	;    u.off - points to entry to be filled 
  2326                              <1> 	;	     in the current directory		
  2327                              <1> 	;    u.base - points to start of u.dirbuf.
  2328                              <1> 	;    r1 - contains i-number of current directory 
  2329                              <1> 	;	
  2330                              <1> 	; ((AX = R1)) output
  2331                              <1> 	;
  2332                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2333                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2334                              <1> 	;
  2335                              <1> 
  2336                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2337 0000448B 31C0                <1> 	xor 	eax, eax
  2338 0000448D BF[90700000]        <1>         mov     edi, u.dirbuf+2
  2339 00004492 89FE                <1> 	mov	esi, edi
  2340 00004494 AB                  <1> 	stosd
  2341 00004495 AB                  <1> 	stosd
  2342                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2343 00004496 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2344                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2345                              <1> 	;mov 	ebp, [u.namep]
  2346 00004498 E8B9060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2347                              <1> 		; esi = physical address (page start + offset)
  2348                              <1> 		; ecx = byte count in the page (1 - 4096)
  2349                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2350                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2351                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2352                              <1> mkdir_1: ; 1: 
  2353 0000449D 45                  <1> 	inc	ebp ; 12/10/2015
  2354                              <1> 	;
  2355                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2356                              <1> 	 ; 01/08/2013
  2357 0000449E AC                  <1> 	lodsb
  2358                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2359 0000449F 20C0                <1> 	and 	al, al
  2360 000044A1 7426                <1> 	jz 	short mkdir_3 	  
  2361                              <1> 		; beq 1f / if null, done
  2362 000044A3 3C2F                <1> 	cmp	al, '/'
  2363                              <1> 		; cmp r1,$'/ / is it a "/"?
  2364 000044A5 7413                <1> 	je	short mkdir_err
  2365                              <1> 	;je	error
  2366                              <1> 		; beq error9 / yes, error
  2367                              <1> 	; 03/02/2022
  2368 000044A7 49                  <1> 	dec	ecx
  2369                              <1> 	; 12/10/2015
  2370                              <1> 	;dec	cx
  2371 000044A8 7505                <1> 	jnz	short mkdir_2
  2372                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2373 000044AA E8AD060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2374                              <1> 		; esi = physical address (page start + offset)
  2375                              <1> 		; ecx = byte count in the page
  2376                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2377                              <1> mkdir_2:
  2378 000044AF 81FF[98700000]      <1> 	cmp     edi, u.dirbuf+10
  2379                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2380                              <1> 				     ; / a char?
  2381 000044B5 74E6                <1> 	je	short mkdir_1
  2382                              <1> 		; beq 1b / yes, go back
  2383 000044B7 AA                  <1> 	stosb
  2384                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2385 000044B8 EBE3                <1> 	jmp 	short mkdir_1
  2386                              <1> 		; br 1b / get next char
  2387                              <1> mkdir_err:
  2388                              <1> 	; 17/06/2015
  2389 000044BA C705[AB700000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2389 000044C2 0000                <1>
  2390 000044C4 E90AF6FFFF          <1> 	jmp	error
  2391                              <1> mkdir_3: ; 1:
  2392 000044C9 A1[70700000]        <1> 	mov	eax, [u.dirp]
  2393 000044CE A3[78700000]        <1> 	mov	[u.off], eax
  2394                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2395                              <1> 				 ; / slot to u.off
  2396                              <1> wdir: 	; 03/02/2022
  2397                              <1> 	; 29/04/2013
  2398 000044D3 C705[7C700000]-     <1>         mov     dword [u.base], u.dirbuf
  2398 000044D9 [8E700000]          <1>
  2399                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2400 000044DD C705[80700000]0A00- <1>         mov     dword [u.count], 10
  2400 000044E5 0000                <1>
  2401                              <1> 		; mov $10.,u.count / u.count = 10
  2402 000044E7 66A1[3C700000]      <1> 	mov	ax, [ii] 
  2403                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2404 000044ED B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2405 000044EF E8C90D0000          <1> 	call 	access
  2406                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2407                              <1> 				 ; / for writing
  2408                              <1> 	; AX = i-number of current directory
  2409                              <1> 	; 01/08/2013
  2410 000044F4 FE05[BD700000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2411                              <1> 	;call	writei
  2412                              <1> 	;	; jsr r0,writei / write into directory
  2413                              <1> 	;retn	
  2414                              <1> 	;	; rts r0
  2415                              <1> 	; 03/02/2022
  2416 000044FA E9AC100000          <1> 	jmp	writei
  2417                              <1> 
  2418                              <1> sysexec:
  2419                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2420                              <1> 	; 03/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18)
  2421                              <1> 	; 23/10/2015
  2422                              <1> 	; 19/10/2015
  2423                              <1> 	; 10/10/2015, 18/10/2015
  2424                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2425                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2426                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2427                              <1> 	; 24/06/2015, 25/06/2015
  2428                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2429                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2430                              <1> 	;
  2431                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2432                              <1> 	; pointed to by 'name' in the sysexec call. 
  2433                              <1> 	; 'sysexec' performs the following operations:
  2434                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2435                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2436                              <1> 	;    3. sets trap vectors to system routines.
  2437                              <1> 	;    4. loads arguments to be passed to executing file into
  2438                              <1> 	;	highest locations of user's core
  2439                              <1> 	;    5. puts pointers to arguments in locations immediately
  2440                              <1> 	;	following arguments.
  2441                              <1> 	;    6.	saves number of arguments in next location.
  2442                              <1> 	;    7. intializes user's stack area so that all registers
  2443                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2444                              <1> 	;	to core when 'sysret' restores registers 
  2445                              <1> 	;	and does an rti.
  2446                              <1> 	;    8. inializes u.r0 and u.sp
  2447                              <1> 	;    9. zeros user's core down to u.r0
  2448                              <1> 	;   10.	reads executable file from storage device into core
  2449                              <1> 	;	starting at location 'core'.
  2450                              <1> 	;   11.	sets u.break to point to end of user's code with
  2451                              <1> 	;	data area appended.
  2452                              <1> 	;   12.	calls 'sysret' which returns control at location
  2453                              <1> 	;	'core' via 'rti' instruction. 		  		
  2454                              <1> 	;
  2455                              <1> 	; Calling sequence:
  2456                              <1> 	;	sysexec; namep; argp
  2457                              <1> 	; Arguments:
  2458                              <1> 	;	namep - points to pathname of file to be executed
  2459                              <1> 	;	argp  - address of table of argument pointers
  2460                              <1> 	;	argp1... argpn - table of argument pointers
  2461                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2462                              <1> 	; Inputs: (arguments)
  2463                              <1> 	; Outputs: -	
  2464                              <1> 	; ...............................................................
  2465                              <1> 	;
  2466                              <1> 	; Retro UNIX 386 v1 modification: 
  2467                              <1> 	;	User application runs in it's own virtual space 
  2468                              <1> 	;	which is izolated from kernel memory (and other
  2469                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2470                              <1> 	;	privilige mode. Virtual start address is always 0.
  2471                              <1> 	;	User's core memory starts at linear address 400000h
  2472                              <1> 	;	(the end of the 1st 4MB).
  2473                              <1> 	;
  2474                              <1> 	; Retro UNIX 8086 v1 modification: 
  2475                              <1> 	;	user/application segment and system/kernel segment
  2476                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2477                              <1> 	;	are different (user's registers are saved to 
  2478                              <1> 	;	and then restored from system's stack.)
  2479                              <1> 	;
  2480                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2481                              <1> 	;	      arguments which were in these registers;
  2482                              <1> 	;	      but, it returns by putting the 1st argument
  2483                              <1> 	;	      in 'u.namep' and the 2nd argument
  2484                              <1> 	;	      on top of stack. (1st argument is offset of the
  2485                              <1> 	;	      file/path name in the user's program segment.)		 	
  2486                              <1> 	
  2487                              <1> 	;call	arg2
  2488                              <1> 	; * name - 'u.namep' points to address of file/path name
  2489                              <1> 	;          in the user's program segment ('u.segmnt')
  2490                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2491                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2492                              <1> 	;          which is on top of stack.
  2493                              <1> 	;
  2494                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2495                              <1> 
  2496                              <1> 	; 23/06/2015 (32 bit modifications)
  2497                              <1> 
  2498 000044FF 891D[74700000]      <1> 	mov	[u.namep], ebx ; argument 1
  2499                              <1>         ; 18/10/2015
  2500 00004505 890D[D4700000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2501 0000450B E8C4040000          <1> 	call	namei
  2502                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2503                              <1> 			     ; / named in sysexec call in r1
  2504                              <1> 	;jc	error
  2505                              <1> 		; br error9
  2506 00004510 731E                <1> 	jnc	short sysexec_0
  2507                              <1> 	;
  2508                              <1> 	; 'file not found !' error
  2509 00004512 C705[AB700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2509 0000451A 0000                <1>
  2510 0000451C E9B2F5FFFF          <1> 	jmp	error 
  2511                              <1> sysexec_not_exf:
  2512                              <1> 	; 'not executable file !' error
  2513 00004521 C705[AB700000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2513 00004529 0000                <1>
  2514 0000452B E9A3F5FFFF          <1> 	jmp	error 
  2515                              <1> sysexec_0:
  2516 00004530 E8B40C0000          <1> 	call	iget
  2517                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2518                              <1> 	; 03/02/2022
  2519 00004535 F605[586D0000]10    <1> 	test	byte [i.flgs], 10h
  2520                              <1>         ;test	word [i.flgs], 10h
  2521                              <1> 		; bit $20,i.flgs / is file executable
  2522 0000453C 74E3                <1> 	jz	short sysexec_not_exf
  2523                              <1> 	;jz	error
  2524                              <1> 		; beq error9
  2525                              <1> 	;;
  2526 0000453E E800150000          <1> 	call	iopen
  2527                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2528                              <1> 			     ; / given in r1 (opens file)
  2529                              <1> 	; AX = i-number of the file
  2530                              <1> 	; 03/02/2022
  2531 00004543 F605[586D0000]20    <1> 	test	byte [i.flgs], 20h
  2532                              <1> 	;test	word [i.flgs], 20h
  2533                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2534 0000454A 7415                <1> 	jz	short sysexec_1
  2535                              <1> 		; beq 1f
  2536 0000454C 803D[A2700000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2537                              <1> 		; tstb u.uid / test user id
  2538 00004553 760C                <1> 	jna	short sysexec_1
  2539                              <1> 		; beq 1f / super user
  2540 00004555 8A0D[5B6D0000]      <1> 	mov	cl, [i.uid]
  2541 0000455B 880D[A2700000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2542                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2543                              <1> 				 ; / as process user id
  2544                              <1> sysexec_1:
  2545                              <1> 	; 03/02/2022
  2546                              <1> 	; 18/10/2215
  2547                              <1> 	; 10/10/2015
  2548                              <1> 	; 21/07/2015, 24/07/2015
  2549                              <1> 	; 24/06/2015, 25/06/2015
  2550                              <1>         ; Moving arguments to the end of [u.upage]
  2551                              <1> 	; (by regarding page borders in user's memory space)
  2552                              <1> 	;
  2553                              <1> 	; 10/10/2015
  2554                              <1> 	; 21/07/2015
  2555 00004561 89E5                <1> 	mov	ebp, esp ; (**)
  2556                              <1> 	; 18/10/2015
  2557 00004563 89EF                <1> 	mov 	edi, ebp
  2558 00004565 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2559                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2560 0000456A 29CF                <1> 	sub	edi, ecx
  2561 0000456C 89FC                <1> 	mov	esp, edi
  2562 0000456E 31C0                <1> 	xor	eax, eax
  2563 00004570 A3[84700000]        <1> 	mov 	[u.nread], eax ; 0
  2564                              <1> 	; 03/02/2022
  2565                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2566                              <1> 	; may leave it with any value after an error))
  2567                              <1> 	;mov	[argc], ax
  2568 00004575 A2[D2700000]        <1> 	mov	[argc], al ; 0
  2569                              <1> 	;
  2570 0000457A 49                  <1> 	dec	ecx ; 256 - 1
  2571 0000457B 890D[80700000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2572                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2573                              <1> sysexec_2:
  2574 00004581 8B35[D4700000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2575 00004587 E864020000          <1> 	call	get_argp
  2576                              <1> 	;mov	ecx, 4 
  2577                              <1> 	; 03/02/2022
  2578 0000458C 31C9                <1> 	xor	ecx, ecx
  2579 0000458E B104                <1> 	mov	cl, 4
  2580                              <1> sysexec_3:
  2581 00004590 21C0                <1> 	and	eax, eax
  2582 00004592 7456                <1> 	jz	short sysexec_6
  2583                              <1> 	; 18/10/2015
  2584 00004594 010D[D4700000]      <1> 	add	[argv], ecx ; 4
  2585 0000459A 66FF05[D2700000]    <1> 	inc	word [argc]
  2586                              <1> 	;
  2587 000045A1 A3[7C700000]        <1> 	mov	[u.base], eax
  2588                              <1>  	; 23/10/2015
  2589 000045A6 66C705[BB700000]00- <1> 	mov	word [u.pcount], 0
  2589 000045AE 00                  <1>
  2590                              <1> sysexec_4:
  2591 000045AF E821120000          <1> 	call	cpass ; get a character from user's core memory
  2592 000045B4 750B                <1>         jnz	short sysexec_5
  2593                              <1> 		; (max. 255 chars + null)
  2594                              <1> 	; 18/10/2015
  2595 000045B6 28C0                <1> 	sub 	al, al
  2596 000045B8 AA                  <1> 	stosb
  2597 000045B9 FF05[84700000]      <1> 	inc	dword [u.nread]
  2598 000045BF EB29                <1> 	jmp	short sysexec_6
  2599                              <1> sysexec_5:
  2600 000045C1 AA                  <1> 	stosb
  2601 000045C2 20C0                <1> 	and 	al, al
  2602 000045C4 75E9                <1> 	jnz	short sysexec_4
  2603                              <1> 	;mov	ecx, 4
  2604                              <1> 	; 03/02/2022
  2605 000045C6 29C9                <1> 	sub	ecx, ecx
  2606 000045C8 B104                <1> 	mov	cl, 4
  2607                              <1> 	;cmp	[ncount], ecx ; 4
  2608                              <1> 	; 03/02/2022
  2609 000045CA 66390D[D0700000]    <1> 	cmp	[ncount], cx ; 4
  2610 000045D1 72AE                <1> 	jb	short sysexec_2
  2611 000045D3 8B35[CC700000]      <1> 	mov	esi, [nbase]
  2612 000045D9 010D[CC700000]      <1> 	add	[nbase], ecx ; 4	
  2613 000045DF 66290D[D0700000]    <1> 	sub	[ncount], cx 
  2614 000045E6 8B06                <1> 	mov	eax, [esi]
  2615 000045E8 EBA6                <1> 	jmp	short sysexec_3
  2616                              <1> sysexec_6:
  2617                              <1> 	; 18/10/2015
  2618                              <1> 	; argument list transfer from user's core memory to
  2619                              <1> 	; kernel stack frame is OK here.
  2620                              <1> 	; [u.nread] = ; argument list length
  2621                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2622                              <1> 	;
  2623                              <1> 	; 18/10/2015
  2624                              <1>         ; 21/07/2015, 24/07/2015
  2625                              <1> 	; 25/06/2015, 02/07/2015
  2626                              <1> 	; 23/06/2015, 24/06/2015
  2627                              <1> 	;
  2628 000045EA 8B1D[B3700000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2629 000045F0 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2630 000045F2 740A                <1> 	jz	short sysexec_7
  2631 000045F4 A1[AF700000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2632 000045F9 E8FEE8FFFF          <1> 	call	deallocate_page_dir
  2633                              <1> sysexec_7:
  2634 000045FE E82EE8FFFF          <1> 	call	make_page_dir
  2635                              <1> 	;jc	short sysexec_14
  2636                              <1> 	;jc	panic  ; allocation error 
  2637                              <1> 		       ; after a deallocation would be nonsence !?
  2638                              <1> 	; 03/02/2022
  2639 00004603 7243                <1> 	jc	short sysexec_panic
  2640                              <1> 
  2641                              <1> 	; 24/07/2015
  2642                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2643                              <1> 	;     of the user's page directory
  2644                              <1> 	;     (It is needed for interrupts!)
  2645                              <1> 	; 18/10/2015
  2646 00004605 8B15[986C0000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2647 0000460B 8B02                <1> 	mov	eax, [edx] ; physical address of
  2648                              <1> 			   ; kernel's first page table (1st 4 MB)
  2649                              <1> 			   ; (PDE 0 of kernel's page directory)
  2650 0000460D 8B15[AF700000]      <1> 	mov 	edx, [u.pgdir]
  2651 00004613 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2652                              <1> 	;
  2653                              <1> 	; 20/07/2015
  2654 00004615 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2655                              <1> 	; 18/10/2015
  2656 0000461A BE[C4700000]        <1> 	mov	esi, pcore ; physical start address
  2657                              <1> sysexec_8:	
  2658 0000461F B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2659 00004624 E826E8FFFF          <1> 	call	make_page_table
  2660                              <1> 	;jc	panic
  2661                              <1> 	; 03/02/2022
  2662 00004629 721D                <1> 	jc	short sysexec_panic
  2663                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2664 0000462B E82DE8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2665                              <1> 	;jc	panic
  2666                              <1> 	; 03/02/2022
  2667 00004630 7216                <1> 	jc	short sysexec_panic
  2668                              <1> 	;
  2669 00004632 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2670                              <1> 	; ebx = virtual address (24/07/2015)
  2671                              <1> 	; 03/02/2022
  2672                              <1> 	;call 	add_to_swap_queue
  2673                              <1> 	; 18/10/2015
  2674 00004634 81FE[C8700000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2675 0000463A 7411                <1> 	je	short sysexec_9 ; yes
  2676 0000463C BE[C8700000]        <1> 	mov	esi, ecore ; physical address of the last page 
  2677                              <1> 	; 20/07/2015
  2678 00004641 BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2679                              <1> 	; ebx = virtual end address + segment base address - 4K
  2680 00004646 EBD7                <1>         jmp     short sysexec_8
  2681                              <1> 
  2682                              <1> sysexec_panic:
  2683                              <1> 	; 03/02/2022
  2684 00004648 E945EDFFFF          <1> 	jmp	panic
  2685                              <1> 
  2686                              <1> sysexec_9:
  2687                              <1> 	; 18/10/2015
  2688                              <1> 	; 26/08/2015
  2689                              <1> 	; 25/06/2015
  2690                              <1> 	; move arguments from kernel stack to [ecore]
  2691                              <1> 	; (argument list/line will be copied from kernel stack
  2692                              <1> 	; frame to the last (stack) page of user's core memory)
  2693                              <1> 	; 18/10/2015
  2694 0000464D 8B3D[C8700000]      <1> 	mov	edi, [ecore]
  2695 00004653 81C700100000        <1> 	add	edi, PAGE_SIZE
  2696                              <1> 	;movzx	eax, word [argc]
  2697                              <1> 	; 03/02/2022
  2698 00004659 31C0                <1> 	xor	eax, eax
  2699 0000465B A0[D2700000]        <1> 	mov	al, [argc]
  2700 00004660 08C0                <1> 	or	al, al
  2701                              <1> 	;or	eax, eax
  2702 00004662 7509                <1> 	jnz	short sysexec_10
  2703 00004664 89FB                <1> 	mov 	ebx, edi
  2704 00004666 83EB04              <1> 	sub	ebx, 4 
  2705 00004669 8903                <1> 	mov	[ebx], eax ; 0
  2706 0000466B EB43                <1> 	jmp 	short sysexec_13
  2707                              <1> sysexec_10:
  2708 0000466D 8B0D[84700000]      <1> 	mov	ecx, [u.nread]
  2709                              <1> 	;mov 	esi, [argv]
  2710 00004673 89E6                <1> 	mov	esi, esp ; start address of argument list
  2711 00004675 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2712                              <1> 	
  2713                              <1> 	;;;;
  2714                              <1> 	; 09/05/2022
  2715                              <1> 	; (move edi -backward- to dword boundary)
  2716                              <1> 	; ((this will prevent 'general protection fault' error
  2717                              <1> 	;  as result of a lodsd or dword move instruction
  2718                              <1> 	;  at the end of argument list))
  2719 00004677 83EF03              <1> 	sub	edi, 3
  2720 0000467A 83E7FC              <1> 	and	edi, ~3 ; (*)
  2721                              <1> 	;;;
  2722                              <1> 
  2723 0000467D 89C2                <1> 	mov	edx, eax
  2724                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2725 0000467F FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2726 00004681 C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2727                              <1> 	; edx <= 128
  2728 00004684 89FB                <1> 	mov	ebx, edi
  2729                              <1> 	; 09/05/2022 (*) - edi is already dword aligned -
  2730                              <1> 	;and	bl, 0FCh ; 32 bit (dword) alignment
  2731 00004686 29D3                <1> 	sub 	ebx, edx
  2732 00004688 89FA                <1> 	mov	edx, edi
  2733 0000468A F3A4                <1> 	rep	movsb
  2734 0000468C 89D6                <1> 	mov 	esi, edx
  2735 0000468E 89DF                <1> 	mov 	edi, ebx
  2736 00004690 BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2737 00004695 2B15[C8700000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2738 0000469B AB                  <1> 	stosd	; eax = argument count	
  2739                              <1> sysexec_11:
  2740 0000469C 89F0                <1> 	mov	eax, esi
  2741 0000469E 01D0                <1> 	add	eax, edx
  2742 000046A0 AB                  <1> 	stosd  ; eax = virtual address
  2743 000046A1 FE0D[D2700000]      <1> 	dec	byte [argc]
  2744 000046A7 7407                <1> 	jz	short sysexec_13
  2745                              <1> sysexec_12:
  2746 000046A9 AC                  <1> 	lodsb
  2747 000046AA 20C0                <1> 	and	al, al
  2748 000046AC 75FB                <1> 	jnz	short sysexec_12
  2749 000046AE EBEC                <1> 	jmp	short sysexec_11
  2750                              <1> 	;
  2751                              <1> 	; 1:
  2752                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2753                              <1> 			     ; / pointers to arguments to be passed
  2754                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2755                              <1> 			      ; / u.quit = 1 take quit
  2756                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2757                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2758                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2759                              <1> 			       ; / system routine
  2760                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2761                              <1> 			       ; / set to take system routine
  2762                              <1> 		; mov $sstack,sp / stack space used during swapping
  2763                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2764                              <1> 		; mov $ecore,r5 / r5 has end of core
  2765                              <1> 		; mov $core,r4 / r4 has start of users core
  2766                              <1> 		; mov r4,u.base / u.base has start of users core
  2767                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2768                              <1> 	; 1:
  2769                              <1> 		; tst (r2)+ / argument char = "nul"
  2770                              <1> 		; bne 1b
  2771                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2772                              <1> 			  ; / end of argument pointer list
  2773                              <1> 	; 1:
  2774                              <1> 	     ; / move arguments to bottom of users core
  2775                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2776                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2777                              <1> 			    ; / ptr list
  2778                              <1> 		; blo 1f / branch to 1f when all arguments
  2779                              <1> 		       ; / are moved
  2780                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2781                              <1> 	; 2:
  2782                              <1> 		; tstb (r3)+
  2783                              <1> 		; bne 2b / scan argument for \0 (nul)
  2784                              <1> 
  2785                              <1> 	; 2:
  2786                              <1> 		; movb -(r3),-(r5) / move argument char 
  2787                              <1> 				 ; / by char starting at "ecore"
  2788                              <1> 		; cmp r3,(r2) / moved all characters in 
  2789                              <1> 			    ; / this argument
  2790                              <1> 		; bhi 2b / branch 2b if not
  2791                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2792                              <1> 			     ; / r5 has pointer to nth arg
  2793                              <1> 		; br 1b / string
  2794                              <1> 	; 1:
  2795                              <1> 		; clrb -(r5)
  2796                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2797                              <1> 			 ; / last word of argument strings
  2798                              <1> 		; mov $core,r2
  2799                              <1> 	
  2800                              <1> 	; 1: / move argument pointers into core following 
  2801                              <1> 	      ; / argument strings
  2802                              <1> 		; cmp r2,r4
  2803                              <1> 		; bhis 1f / branch to 1f when all pointers
  2804                              <1> 			; / are moved
  2805                              <1> 		; mov (r2)+,-(r5)
  2806                              <1> 		; br 1b
  2807                              <1> 	; 1:
  2808                              <1> 		; sub $core,r4 / gives number of arguments *2
  2809                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2810                              <1> 		       ; / the number of args stored
  2811                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2812                              <1> 			     ; / of the argument pointers
  2813                              <1> sysexec_13:
  2814                              <1> 	; 19/10/2015
  2815                              <1> 	; 18/10/2015
  2816                              <1> 	; 29/07/2015
  2817                              <1> 	; 24/07/2015, 25/07/2015
  2818                              <1> 	; 25/06/2015, 20/07/2015
  2819                              <1> 	; 23/06/2015, 24/06/2015
  2820                              <1> 	;
  2821                              <1> 	; moving arguments to [ecore] is OK here..
  2822                              <1> 	; 18/10/2015
  2823 000046B0 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2824                              <1> 	; ebx = beginning addres of argument list pointers
  2825                              <1> 	;	in user's stack
  2826                              <1> 	; 19/10/2015
  2827 000046B2 2B1D[C8700000]      <1> 	sub 	ebx, [ecore]
  2828 000046B8 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2829                              <1> 			; end of core - 4096 (last page)
  2830                              <1> 			; (virtual address)
  2831 000046BE 891D[D4700000]      <1> 	mov	[argv], ebx
  2832 000046C4 891D[88700000]      <1> 	mov	[u.break], ebx ; available user memory
  2833                              <1> 	;
  2834 000046CA 29C0                <1> 	sub	eax, eax
  2835 000046CC C705[80700000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2835 000046D4 0000                <1>
  2836                              <1> 		; mov $14,u.count
  2837 000046D6 C705[6C700000]-     <1> 	mov	dword [u.fofp], u.off
  2837 000046DC [78700000]          <1>
  2838                              <1> 		; mov $u.off,u.fofp
  2839 000046E0 A3[78700000]        <1> 	mov	[u.off], eax ; 0
  2840                              <1> 		; clr u.off / set offset in file to be read to zero
  2841                              <1> 	; 25/07/2015
  2842 000046E5 A3[7C700000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2843                              <1> 	; 25/06/2015 
  2844 000046EA 66A1[3C700000]      <1> 	mov	ax, [ii]
  2845                              <1> 	; AX = i-number of the executable file
  2846 000046F0 E8C80C0000          <1> 	call	readi
  2847                              <1> 		; jsr r0,readi / read in first six words of 
  2848                              <1> 			; / user's file, starting at $core
  2849                              <1> 		; mov sp,r5 / put users stack address in r5
  2850                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2851                              <1> 				; / from r5 (leaves number of words
  2852                              <1> 				; / less 26 available for
  2853                              <1> 			     	; / program in user core
  2854                              <1> 		; mov r5,u.count /
  2855                              <1> 	; 25/06/2015
  2856 000046F5 8B0D[88700000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2857 000046FB 890D[80700000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2858                              <1> 	;
  2859 00004701 8B0D[84700000]      <1> 	mov	ecx, [u.nread]
  2860 00004707 890D[88700000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2861 0000470D 80F920              <1> 	cmp	cl, 32
  2862 00004710 7540                <1>         jne     short sysexec_15
  2863                              <1> 	;:
  2864                              <1> 	; 25/06/2015
  2865                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2866                              <1> 	; 18/10/2015
  2867 00004712 8B35[C4700000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2868                              <1> 		             ; (phys. start addr. of the exec. file)
  2869 00004718 AD                  <1> 	lodsd
  2870 00004719 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBh, 1Eh -> jump to +32
  2871 0000471D 7533                <1> 	jne	short sysexec_15
  2872                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2873                              <1> 			      ; / if file is standard a.out format
  2874                              <1> 		; bne 1f / branch, if not standard format
  2875 0000471F AD                  <1> 	lodsd
  2876 00004720 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2877 00004722 AD                  <1> 	lodsd
  2878 00004723 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2879                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2880                              <1> 		              ; / number of bytes in program text	
  2881                              <1> 		; sub $14,r5 / subtract 12
  2882 00004725 89CB                <1> 	mov	ebx, ecx
  2883                              <1> 	;
  2884                              <1> 	; 25/06/2015
  2885                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2886                              <1> 	;	and SINGLIX operating systems (as code template).
  2887                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2888                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2889                              <1> 	;	Overrun is not possible for current version. 	
  2890                              <1> 	;
  2891 00004727 AD                  <1> 	lodsd	
  2892 00004728 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2893 0000472A 3B1D[80700000]      <1> 	cmp	ebx, [u.count]
  2894 00004730 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2895                              <1> 	;
  2896                              <1> 	; 24/07/2015
  2897                              <1> 	; add bss section size to [u.break]
  2898 00004732 0105[88700000]      <1> 	add 	[u.break], eax
  2899                              <1> 	;
  2900 00004738 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2901                              <1> 	;cmp	ecx, [u.count]
  2902                              <1> 	;jnb	short sysexec_16
  2903                              <1> 		; cmp r5,u.count /
  2904                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2905 0000473B 890D[80700000]      <1> 	mov	[u.count], ecx ; required read count
  2906                              <1> 		; mov r5,u.count
  2907                              <1> 	;
  2908 00004741 EB2A                <1> 	jmp	short sysexec_16
  2909                              <1> 	;
  2910                              <1> sysexec_14:
  2911                              <1> 	; 23/06/2015
  2912                              <1> 	; insufficient (out of) memory
  2913 00004743 C705[AB700000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2913 0000474B 0000                <1>
  2914 0000474D E981F3FFFF          <1> 	jmp	error
  2915                              <1> 	;
  2916                              <1> sysexec_15:
  2917                              <1> 	; 25/06/2015
  2918 00004752 0FB715[5C6D0000]    <1>         movzx   edx, word [i.size] ; file size
  2919 00004759 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2920 0000475B 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2921 0000475D 01D1                <1> 	add	ecx, edx ; [i.size]
  2922 0000475F 3B0D[80700000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2923 00004765 77DC                <1> 	ja	short sysexec_14
  2924 00004767 8915[80700000]      <1> 	mov	[u.count], edx
  2925                              <1> sysexec_16:
  2926 0000476D 66A1[3C700000]      <1> 	mov	ax, [ii] ; i-number
  2927 00004773 E8450C0000          <1> 	call	readi
  2928                              <1> 		; add core+10,u.nread / add size of user data area 
  2929                              <1> 		                    ; / to u.nread
  2930                              <1> 		; br 2f
  2931                              <1> 	; 1:
  2932                              <1> 		; jsr r0,readi / read in rest of file
  2933                              <1> 	; 2:
  2934 00004778 8B0D[84700000]      <1> 	mov	ecx, [u.nread]
  2935 0000477E 010D[88700000]      <1> 	add	[u.break], ecx
  2936                              <1> 		; mov u.nread,u.break / set users program break to end of 
  2937                              <1> 				    ; / user code
  2938                              <1> 		; add $core+14,u.break / plus data area
  2939                              <1> sysexec_17: ; 20/07/2015
  2940                              <1> 	; 03/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2941                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2942                              <1> 	; ('iclose' is not needed for regular files, from now on)
  2943                              <1> 	;;mov	ax, [ii] ; i-number
  2944                              <1> 	;call	iclose
  2945                              <1> 	;	; jsr r0,iclose / does nothing
  2946 00004784 31C0                <1>         xor     eax, eax
  2947 00004786 FEC0                <1> 	inc	al
  2948 00004788 66A3[9A700000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  2949 0000478E 66A3[9C700000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  2950                              <1> 	; 02/07/2015
  2951 00004794 833D[B3700000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  2952 0000479B 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  2953                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  2954 0000479D 8B15[986C0000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  2955 000047A3 8915[B3700000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  2956                              <1> sysexec_18:
  2957                              <1> 	; 18/10/2015
  2958                              <1> 	; 05/08/2015
  2959                              <1> 	; 29/07/2015
  2960 000047A9 8B2D[D4700000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  2961                              <1> 			    ; list pointers (argument count)
  2962 000047AF FA                  <1> 	cli
  2963 000047B0 8B25[346C0000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  2964                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  2965                              <1> 			    ; for this process	 
  2966                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  2967                              <1> 	;xor	eax, eax ; 0
  2968 000047B6 FEC8                <1> 	dec	al ; eax = 0
  2969 000047B8 66BA2300            <1> 	mov	dx, UDATA
  2970 000047BC 6652                <1> 	push	dx  ; user's stack segment
  2971 000047BE 55                  <1> 	push	ebp ; user's stack pointer
  2972                              <1> 		    ; (points to number of arguments)
  2973 000047BF FB                  <1> 	sti
  2974 000047C0 9C                  <1> 	pushfd	; EFLAGS
  2975                              <1> 		; Set IF for enabling interrupts in user mode	
  2976                              <1> 	;or	dword [esp], 200h 
  2977                              <1> 	;
  2978                              <1> 	;mov	bx, UCODE
  2979                              <1> 	;push	bx ; user's code segment
  2980 000047C1 6A1B                <1> 	push	UCODE
  2981                              <1> 	;push	0
  2982 000047C3 50                  <1> 	push	eax ; EIP (=0) - start address -	
  2983                              <1> 		; clr -(r5) / popped into ps when rti in 
  2984                              <1> 			  ; / sysrele is executed
  2985                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  2986                              <1> 		                ; / in sysrele is executed
  2987                              <1> 		;mov r5,0f / load second copyz argument
  2988                              <1> 		;tst -(r5) / decrement r5
  2989 000047C4 8925[54700000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  2990                              <1> 	; 05/08/2015
  2991                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  2992                              <1> 	; ('push dx' would cause to general protection fault, 
  2993                              <1> 	; after 'pop ds' etc.)
  2994                              <1> 	;
  2995                              <1> 	;; push dx ; ds (UDATA)
  2996                              <1> 	;; push dx ; es (UDATA)
  2997                              <1> 	;; push dx ; fs (UDATA)
  2998                              <1> 	;; push dx ; gs (UDATA)
  2999                              <1> 	;
  3000                              <1> 	; This is a trick to prevent general protection fault
  3001                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3002 000047CA 8EC2                <1> 	mov 	es, dx ; UDATA
  3003 000047CC 06                  <1> 	push 	es ; ds (UDATA)
  3004 000047CD 06                  <1> 	push 	es ; es (UDATA)
  3005 000047CE 06                  <1> 	push 	es ; fs (UDATA)
  3006 000047CF 06                  <1> 	push	es ; gs (UDATA)
  3007 000047D0 66BA1000            <1> 	mov	dx, KDATA
  3008 000047D4 8EC2                <1> 	mov	es, dx
  3009                              <1> 	;
  3010                              <1> 	;; pushad simulation
  3011 000047D6 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3012 000047D8 50                  <1> 	push	eax ; eax (0)
  3013 000047D9 50                  <1> 	push	eax ; ecx (0)
  3014 000047DA 50                  <1> 	push	eax ; edx (0)
  3015 000047DB 50                  <1> 	push	eax ; ebx (0)
  3016 000047DC 55                  <1> 	push	ebp ; esp before pushad
  3017 000047DD 50                  <1> 	push	eax ; ebp (0)
  3018 000047DE 50                  <1> 	push	eax ; esi (0)		
  3019 000047DF 50                  <1> 	push	eax ; edi (0)	
  3020                              <1> 	;
  3021 000047E0 A3[5C700000]        <1> 	mov	[u.r0], eax ; eax = 0
  3022 000047E5 8925[58700000]      <1> 	mov	[u.usp], esp
  3023                              <1> 		; mov r5,u.r0 /
  3024                              <1> 		; sub $16.,r5 / skip 8 words
  3025                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3026                              <1> 		;             / effectively zeroes all regs
  3027                              <1> 			    ; / when sysrele is executed
  3028                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3029                              <1> 		; clr u.break
  3030                              <1> 		; mov r5,sp / point sp to user's stack
  3031                              <1> 	;
  3032 000047EB E905F3FFFF          <1> 	jmp	sysret0
  3033                              <1> 	;jmp	sysret
  3034                              <1> 		; br sysret3 / return to core image at $core
  3035                              <1> 
  3036                              <1> get_argp:
  3037                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  3038                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3039                              <1> 	; 18/10/2015 (nbase, ncount)
  3040                              <1> 	; 21/07/2015
  3041                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3042                              <1> 	; Get (virtual) address of argument from user's core memory
  3043                              <1> 	;
  3044                              <1> 	; INPUT:
  3045                              <1> 	;	esi = virtual address of argument pointer
  3046                              <1> 	; OUTPUT:
  3047                              <1> 	;	eax = virtual address of argument
  3048                              <1> 	;
  3049                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3050                              <1> 	;
  3051 000047F0 833D[B3700000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3052                              <1> 				    ; (the caller is kernel)
  3053                              <1>         ;jna	short get_argpk
  3054                              <1> 	; 03/02/2022
  3055 000047F7 7719                <1> 	ja	short get_argp5
  3056                              <1> get_argpk:
  3057                              <1> 	; Argument is in kernel's memory space
  3058 000047F9 66C705[D0700000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3058 00004801 10                  <1>
  3059 00004802 8935[CC700000]      <1> 	mov	[nbase], esi
  3060 00004808 8305[CC700000]04    <1> 	add	dword [nbase], 4
  3061 0000480F 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3062 00004811 C3                  <1> 	retn
  3063                              <1> get_argp5:
  3064 00004812 89F3                <1>      	mov	ebx, esi
  3065 00004814 E89FE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3066 00004819 7257                <1>         jc	short get_argp_err ; 03/02/2022 (short jump)
  3067 0000481B A3[CC700000]        <1> 	mov 	[nbase], eax ; physical address	
  3068 00004820 66890D[D0700000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3069 00004827 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3070                              <1> 	;cmp	cx, ax ; 4
  3071                              <1> 	; 03/02/2022
  3072 0000482C 39C1                <1> 	cmp	ecx, eax
  3073 0000482E 734C                <1> 	jnb	short get_argp2
  3074 00004830 89F3                <1> 	mov	ebx, esi
  3075 00004832 01CB                <1> 	add	ebx, ecx
  3076 00004834 E87FE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3077 00004839 7237                <1> 	jc	short get_argp_err
  3078                              <1> 	;push	esi
  3079 0000483B 89C6                <1> 	mov	esi, eax
  3080 0000483D 66870D[D0700000]    <1> 	xchg	cx, [ncount]
  3081 00004844 8735[CC700000]      <1> 	xchg	esi, [nbase]
  3082 0000484A B504                <1> 	mov	ch, 4
  3083 0000484C 28CD                <1> 	sub	ch, cl
  3084                              <1> get_argp0:
  3085 0000484E AC                  <1> 	lodsb
  3086                              <1> 	;push	ax
  3087                              <1> 	; 03/02/2022
  3088 0000484F 50                  <1> 	push	eax
  3089 00004850 FEC9                <1> 	dec	cl
  3090 00004852 75FA                <1>         jnz     short get_argp0
  3091 00004854 8B35[CC700000]      <1> 	mov	esi, [nbase]
  3092                              <1> 	; 21/07/2015
  3093 0000485A 0FB6C5              <1> 	movzx	eax, ch
  3094 0000485D 0105[CC700000]      <1> 	add	[nbase], eax
  3095 00004863 662905[D0700000]    <1> 	sub	[ncount], ax
  3096                              <1> get_argp1:
  3097 0000486A AC                  <1> 	lodsb
  3098 0000486B FECD                <1> 	dec	ch
  3099 0000486D 7423                <1>         jz      short get_argp3
  3100                              <1>         ;push	ax
  3101                              <1> 	; 03/02/2022
  3102 0000486F 50                  <1> 	push	eax
  3103 00004870 EBF8                <1> 	jmp     short get_argp1
  3104                              <1> get_argp_err:
  3105 00004872 A3[AB700000]        <1> 	mov	[u.error], eax
  3106 00004877 E957F2FFFF          <1> 	jmp	error
  3107                              <1> get_argp2:
  3108                              <1> 	; 21/07/2015
  3109                              <1> 	;mov	eax, 4
  3110 0000487C 8B15[CC700000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3111 00004882 0105[CC700000]      <1> 	add	[nbase], eax
  3112 00004888 662905[D0700000]    <1> 	sub	[ncount], ax
  3113                              <1> 	;
  3114 0000488F 8B02                <1> 	mov	eax, [edx]
  3115 00004891 C3                  <1> 	retn
  3116                              <1> get_argp3:
  3117 00004892 B103                <1> 	mov	cl, 3
  3118                              <1> get_argp4:
  3119 00004894 C1E008              <1> 	shl	eax, 8
  3120                              <1> 	;pop	dx
  3121                              <1> 	; 03/02/2022
  3122 00004897 5A                  <1> 	pop	edx
  3123 00004898 88D0                <1> 	mov 	al, dl
  3124 0000489A E2F8                <1>         loop    get_argp4
  3125                              <1> 	;pop	esi
  3126 0000489C C3                  <1> 	retn	
  3127                              <1> 
  3128                              <1> sysfstat:
  3129                              <1> 	; 09/05/2022 (Retro UNIX 386 v1, Kernel v0.2.0.19)
  3130                              <1> 	;	([idev] return in eax)
  3131                              <1> 	;	0 = root device
  3132                              <1> 	;	1 = mounted device (>0)
  3133                              <1> 	; 03/02/2022
  3134                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3135                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3136                              <1> 	;
  3137                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3138                              <1> 	; on open files instead of files given by name. It puts the
  3139                              <1> 	; buffer address on the stack, gets the i-number and
  3140                              <1> 	; checks to see if the file is open for reading or writing.
  3141                              <1> 	; If the file is open for writing (i-number is negative)
  3142                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3143                              <1> 	; is made.	
  3144                              <1> 	;
  3145                              <1> 	; Calling sequence:
  3146                              <1> 	;	sysfstat; buf
  3147                              <1> 	; Arguments:
  3148                              <1> 	;	buf - buffer address
  3149                              <1> 	;
  3150                              <1> 	; Inputs: *u.r0 - file descriptor
  3151                              <1> 	; Outputs: buffer is loaded with file information
  3152                              <1> 	; ...............................................................
  3153                              <1> 	;				
  3154                              <1> 	; Retro UNIX 8086 v1 modification:
  3155                              <1> 	;       'sysfstat' system call has two arguments; so,
  3156                              <1> 	;	* 1st argument, file descriptor is in BX register
  3157                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3158                              <1> 
  3159                              <1> 	; / set status of open file
  3160                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3161 0000489D 51                  <1> 	push	ecx
  3162                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3163                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3164                              <1> 		; jsr r0,getf / get the files i-number
  3165                              <1> 	; BX = file descriptor (file number)
  3166 0000489E E8FE000000          <1> 	call	getf1
  3167                              <1> 	; 03/02/2022
  3168 000048A3 21C0                <1> 	and	eax, eax
  3169                              <1> 	;and	ax, ax ; i-number of the file
  3170                              <1> 		; tst	r1 / is it 0?
  3171                              <1> 	;jz	error
  3172                              <1> 		; beq error3 / yes, error
  3173 000048A5 750F                <1> 	jnz	short sysfstat1
  3174 000048A7 C705[AB700000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3174 000048AF 0000                <1>
  3175 000048B1 E91DF2FFFF          <1> 	jmp	error
  3176                              <1> sysfstat1:
  3177 000048B6 80FC80              <1> 	cmp	ah, 80h
  3178 000048B9 7222                <1>         jb      short sysstat1
  3179                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3180 000048BB 66F7D8              <1> 	neg	ax
  3181                              <1> 		; neg r1 / make it positive, then branch
  3182 000048BE EB1D                <1> 	jmp	short sysstat1
  3183                              <1> 		; br 1f / to 1f
  3184                              <1> sysstat:
  3185                              <1> 	; 09/05/2022 (Retro UNIX 386 v1, Kernel v0.2.0.19)
  3186                              <1> 	;	([idev] return in eax)
  3187                              <1> 	;	0 = root device
  3188                              <1> 	;	1 = mounted device (>0)
  3189                              <1> 	; 03/02/2022
  3190                              <1> 	; 18/10/2015
  3191                              <1> 	; 07/10/2015
  3192                              <1> 	; 02/09/2015
  3193                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3194                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3195                              <1> 	;
  3196                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3197                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3198                              <1> 	; long and information about the file placed in it.	
  3199                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3200                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3201                              <1> 	; is then loaded and the results are given in the UNIX
  3202                              <1> 	; Programmers Manual sysstat (II).	
  3203                              <1> 	;
  3204                              <1> 	; Calling sequence:
  3205                              <1> 	;	sysstat; name; buf
  3206                              <1> 	; Arguments:
  3207                              <1> 	;	name - points to the name of the file
  3208                              <1> 	;	buf - address of a 34 bytes buffer
  3209                              <1> 	; Inputs: -
  3210                              <1> 	; Outputs: buffer is loaded with file information
  3211                              <1> 	; ...............................................................
  3212                              <1> 	;				
  3213                              <1> 	; Retro UNIX 8086 v1 modification: 
  3214                              <1> 	;       'sysstat' system call has two arguments; so,
  3215                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3216                              <1> 	;	to get sysstat system call arguments from the user;
  3217                              <1> 	;	* 1st argument, name is pointed to by BX register
  3218                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3219                              <1> 	;
  3220                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3221                              <1> 	;	      arguments which were in these registers;
  3222                              <1> 	;	      but, it returns by putting the 1st argument
  3223                              <1> 	;	      in 'u.namep' and the 2nd argument
  3224                              <1> 	;	      on top of stack. (1st argument is offset of the
  3225                              <1> 	;	      file/path name in the user's program segment.)		 	
  3226                              <1> 	
  3227                              <1> 	; / ; name of file; buffer - get files status
  3228                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3229 000048C0 891D[74700000]      <1> 	mov	[u.namep], ebx
  3230 000048C6 51                  <1> 	push	ecx
  3231 000048C7 E808010000          <1> 	call	namei
  3232                              <1> 		; jsr r0,namei / get the i-number for the file
  3233                              <1> 	;jc	error
  3234                              <1> 		; br error3 / no such file, error
  3235 000048CC 730F                <1> 	jnc	short sysstat1
  3236                              <1> 	; pop 	ecx
  3237                              <1> sysstat_err0:
  3238                              <1> 	; 'file not found !' error
  3239 000048CE C705[AB700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3239 000048D6 0000                <1>
  3240 000048D8 E9F6F1FFFF          <1> 	jmp	error
  3241                              <1> 
  3242                              <1> ;statx: db 0
  3243                              <1> 
  3244                              <1> sysstat1: ; 1:
  3245 000048DD E807090000          <1> 	call	iget
  3246                              <1> 		; jsr r0,iget / get the i-node into core
  3247                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3248                              <1> 	; 02/09/2015
  3249 000048E2 8F05[7C700000]      <1> 	pop	dword [u.base]
  3250                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3251 000048E8 E861000000          <1> 	call	sysstat_gpa ; get physical address
  3252 000048ED 730A                <1> 	jnc 	short sysstat2
  3253                              <1> sysstat_err1:
  3254 000048EF A3[AB700000]        <1> 	mov	dword [u.error], eax ; error code
  3255 000048F4 E9DAF1FFFF          <1> 	jmp	error
  3256                              <1> sysstat2:
  3257 000048F9 A0[3C700000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3258 000048FE AA                  <1> 	stosb
  3259 000048FF FF05[7C700000]      <1> 	inc 	dword [u.base]
  3260                              <1> 	;dec 	cx
  3261                              <1> 	; 03/02/2022
  3262 00004905 49                  <1> 	dec	ecx
  3263 00004906 7505                <1> 	jnz	short sysstat3
  3264 00004908 E841000000          <1> 	call	sysstat_gpa
  3265                              <1> 	;jc	short sysstat_err1
  3266                              <1> sysstat3:
  3267 0000490D A0[3D700000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3268 00004912 AA                  <1> 	stosb
  3269                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3270 00004913 FF05[7C700000]      <1> 	inc 	dword [u.base]
  3271                              <1> 	;;dec 	word [u.pcount]
  3272                              <1> 	;dec	cx
  3273                              <1> 	; 03/02/2022
  3274 00004919 49                  <1> 	dec	ecx
  3275 0000491A 7505                <1> 	jnz	short sysstat4
  3276 0000491C E82D000000          <1> 	call	sysstat_gpa
  3277                              <1> 	;jc	short sysstat_err1	
  3278                              <1> sysstat4:
  3279 00004921 BE[586D0000]        <1> 	mov	esi, inode
  3280                              <1> 		; mov $inode,r2 / r2 points to i-node
  3281                              <1> sysstat5: ; 1:
  3282 00004926 A4                  <1> 	movsb
  3283                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3284 00004927 FF05[7C700000]      <1> 	inc 	dword [u.base]
  3285                              <1> 	;;dec 	word [u.pcount]
  3286                              <1> 	;dec	cx
  3287                              <1> 	; 03/02/2022
  3288 0000492D 49                  <1> 	dec	ecx
  3289 0000492E 7505                <1> 	jnz	short sysstat6
  3290 00004930 E819000000          <1> 	call	sysstat_gpa
  3291                              <1> 	;jc	short sysstat_err1
  3292                              <1> sysstat6:		
  3293 00004935 81FE[786D0000]      <1> 	cmp	esi, inode + 32
  3294                              <1> 		; cmp r2,$inode+32 / done?
  3295 0000493B 75E9                <1> 	jne	short sysstat5
  3296                              <1> 		; bne 1b / no, go back
  3297                              <1> 
  3298                              <1> 	;;;
  3299                              <1> 	; 09/05/2022
  3300                              <1> 	;*** additional feature *** -retro unix only- 
  3301                              <1> 	;
  3302                              <1> 	; !! return device number -of current inode- in eax !!
  3303                              <1> 	;
  3304                              <1> 	; (modification reason/purpose:
  3305                              <1> 	; to improve 'pwd' command's pathname output/result
  3306                              <1> 	; and to correct 'cp' command's 'can not copy file itself'
  3307                              <1> 	; error due to same inode numbers in root file system
  3308                              <1> 	; and mounted file system.)
  3309                              <1> 	;
  3310 0000493D 29C0                <1> 	sub	eax, eax
  3311 0000493F A0[3E700000]        <1> 	mov	al, [idev] ; [cdev]
  3312 00004944 A3[5C700000]        <1> 	mov	[u.r0], eax
  3313                              <1> 	;;;  
  3314                              <1> 
  3315 00004949 E9A5F1FFFF          <1> 	jmp	sysret
  3316                              <1> 		; br sysret3 / return through sysret
  3317                              <1> 	;
  3318                              <1> sysstat_gpa: ; get physical address of file status buffer
  3319                              <1> 	; 02/09/2015
  3320 0000494E 8B1D[7C700000]      <1> 	mov 	ebx, [u.base]
  3321                              <1> 	; 07/10/2015
  3322 00004954 E85FE8FFFF          <1> 	call	get_physical_addr ; get physical address
  3323                              <1> 	;jc	short sysstat_gpa1
  3324 00004959 7294                <1> 	jc	short sysstat_err1
  3325                              <1> 	; 18/10/2015
  3326 0000495B 89C7                <1> 	mov	edi, eax ; physical address
  3327                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3328                              <1> ;sysstat_gpa1:
  3329 0000495D C3                  <1> 	retn
  3330                              <1> 
  3331                              <1> fclose:
  3332                              <1> 	; 03/02/2022
  3333                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3334                              <1> 	;            (32 bit offset pointer modification)
  3335                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3336                              <1> 	;
  3337                              <1> 	; Given the file descriptor (index to the u.fp list)
  3338                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3339                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3340                              <1> 	; u.fp list is cleared. If all the processes that opened
  3341                              <1> 	; that file close it, then fsp etry is freed and the file
  3342                              <1> 	; is closed. If not a return is taken. 
  3343                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3344                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3345                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3346                              <1> 	; a check is made to see if the file is special.	
  3347                              <1> 	;
  3348                              <1> 	; INPUTS ->
  3349                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3350                              <1> 	;    u.fp - list of entries in the fsp table
  3351                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3352                              <1> 	; OUTPUTS ->
  3353                              <1> 	;    r1 - contains the same file descriptor
  3354                              <1> 	;    r2 - contains i-number
  3355                              <1> 	;
  3356                              <1> 	; ((AX = R1))
  3357                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3358                              <1> 	;
  3359                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3360                              <1> 	;              if i-number of the file is 0. (error)  	
  3361                              <1> 
  3362                              <1> 	;movzx	edx, ax ; **
  3363                              <1> 	; 03/02/2022
  3364                              <1> 	;movzx	edx, al
  3365 0000495E 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 03/02/2022
  3366 00004960 50                  <1> 	push	eax ; ***
  3367                              <1> 	;push	ax ; ***
  3368                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3369                              <1> 			     ; / the index to u.fp list)
  3370 00004961 E839000000          <1> 	call	getf
  3371                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3372                              <1> 			    ; / cdev has device =, u.fofp 
  3373                              <1> 			    ; / points to 3rd word of fsp entry
  3374 00004966 6683F801            <1> 	cmp	ax, 1 ; r1
  3375                              <1> 		; tst r1 / is i-number 0?
  3376 0000496A 7231                <1> 	jb	short fclose_2
  3377                              <1> 		; beq 1f / yes, i-node not active so return
  3378                              <1> 		; tst (r0)+ / no, jump over error return
  3379 0000496C 89D3                <1> 	mov	ebx, edx ; **
  3380                              <1> 	; 03/02/2022
  3381 0000496E 89C2                <1> 	mov	edx, eax ; *
  3382                              <1> 	;mov 	dx, ax ; *
  3383                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3384                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3385                              <1> 			    ; / which is index to u.fp ; **
  3386 00004970 C683[62700000]00    <1> 	mov	byte [ebx+u.fp], 0
  3387                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3388 00004977 8B1D[6C700000]      <1> 	mov	ebx, [u.fofp]
  3389                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3390                              <1> fclose_0:
  3391 0000497D FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3392                              <1> 		; decb 2(r1) / decrement the number of processes 
  3393                              <1> 			   ; / that have opened the file
  3394 00004980 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3395                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3396                              <1> 	;
  3397                              <1> 	; 03/02/2022
  3398 00004982 52                  <1> 	push	edx ; *
  3399                              <1> 	;push	dx ; *
  3400                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3401                              <1> 	;xor	ax, ax ; 0
  3402                              <1> 	; 03/02/2022
  3403 00004983 31C0                <1> 	xor	eax, eax
  3404 00004985 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3405                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3406 00004989 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3407                              <1> 		; tstb	3(r1) / has this file been deleted
  3408 0000498C 20C0                <1> 	and	al, al
  3409 0000498E 7407                <1> 	jz	short fclose_1
  3410                              <1> 		; beq 2f / no, branch
  3411                              <1> 	; 03/02/2022
  3412 00004990 89D0                <1> 	mov	eax, edx
  3413                              <1> 	;mov	ax, dx ; *
  3414                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3415                              <1> 	; AX = inode number
  3416 00004992 E8A7040000          <1> 	call	anyi
  3417                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3418                              <1> 			    ; / check if file appears in fsp again
  3419                              <1> fclose_1: ; 2:
  3420                              <1> 	; 03/02/2022
  3421 00004997 58                  <1> 	pop	eax ; * 
  3422                              <1> 	;pop	ax ; *
  3423                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3424 00004998 E8E5110000          <1> 	call	iclose ; close if it is special file 
  3425                              <1> 		; jsr r0,iclose / check to see if its a special file
  3426                              <1> fclose_2: ; 1:
  3427                              <1> 	; 03/02/2022
  3428 0000499D 58                  <1> 	pop	eax ; ***
  3429                              <1> 	;pop	ax ; ***
  3430                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3431 0000499E C3                  <1> 	retn
  3432                              <1> 		; rts r0
  3433                              <1> 
  3434                              <1> getf:	; / get the device number and the i-number of an open file
  3435                              <1> 	; 03/02/2022
  3436                              <1> 	; 13/05/2015
  3437                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3438                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3439                              <1> 	;
  3440 0000499F 89C3                <1> 	mov	ebx, eax
  3441                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3442                              <1> 	; 03/02/2022
  3443 000049A1 29C0                <1> 	sub	eax, eax
  3444                              <1> 	;
  3445 000049A3 83FB0A              <1> 	cmp	ebx, 10
  3446                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3447 000049A6 732B                <1>         jnb	short getf2 ; 13/05/2015
  3448                              <1> 	;jnb	error
  3449                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3450                              <1> 			    ; / index in fsp table
  3451                              <1> 	; 03/02/2022
  3452 000049A8 8A83[62700000]      <1> 	mov	al, [ebx+u.fp]
  3453                              <1> 	;mov	bl, [ebx+u.fp]
  3454                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3455                              <1> 		                  ; / in fsp table
  3456                              <1> 	; 03/02/2022
  3457 000049AE 08C0                <1> 	or	al, al
  3458 000049B0 7421                <1> 	jz	short getf2
  3459                              <1> 	;or	bl, bl
  3460                              <1> 	;jnz	short getf3
  3461                              <1> 	;;jz	short getf4
  3462                              <1> 		; beq 1f / if its zero return
  3463                              <1> ;getf2:
  3464                              <1> ;	; 'File not open !' error (ax=0)
  3465                              <1> ;	sub	eax, eax
  3466                              <1> ;	retn
  3467                              <1> 
  3468                              <1> getf3:	
  3469                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3470                              <1> 	;
  3471                              <1> 	; 'fsp' table (10 bytes/entry)
  3472                              <1> 	; bit 15				   bit 0
  3473                              <1> 	; ---|-------------------------------------------
  3474                              <1> 	; r/w|		i-number of open file
  3475                              <1> 	; ---|-------------------------------------------
  3476                              <1> 	;		   device number
  3477                              <1> 	; -----------------------------------------------
  3478                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3479                              <1> 	; -----------------------------------------------
  3480                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3481                              <1> 	; ----------------------|------------------------
  3482                              <1> 	;  flag that says file 	| number of processes
  3483                              <1> 	;   has been deleted	| that have file open 
  3484                              <1> 	; ----------------------|------------------------
  3485                              <1> 	;
  3486                              <1> 	;mov	eax, 10
  3487                              <1> 	; 03/02/2022
  3488 000049B2 B30A                <1> 	mov	bl, 10
  3489 000049B4 F6E3                <1> 	mul	bl
  3490 000049B6 BB[226E0000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3491 000049BB 01C3                <1> 	add	ebx, eax
  3492                              <1> 		; asl r1
  3493                              <1> 		; asl r1 / multiply by 8 to get index into 
  3494                              <1> 		       ; / fsp table entry
  3495                              <1> 		; asl r1
  3496                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3497                              <1> 			      ; / in the fsp entry
  3498 000049BD 891D[6C700000]      <1> 	mov	[u.fofp], ebx
  3499                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3500                              <1> 			      ; / in fsp entry in u.fofp
  3501 000049C3 4B                  <1> 	dec	ebx
  3502 000049C4 4B                  <1> 	dec	ebx
  3503                              <1> 	;mov	al, [ebx]
  3504 000049C5 668B03              <1> 	mov	ax, [ebx]
  3505                              <1> 	;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3506 000049C8 66A3[40700000]      <1> 	mov	[cdev], ax ; ;;in fact (!) 
  3507                              <1> 			     ;;dev number is in 1 byte
  3508                              <1> 		; mov -(r1),cdev / remove the device number  cdev
  3509 000049CE 4B                  <1> 	dec	ebx
  3510 000049CF 4B                  <1> 	dec	ebx
  3511 000049D0 668B03              <1> 	mov	ax, [ebx]
  3512                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3513                              <1> getf2:	; 03/02/2022
  3514                              <1> getf4:	; 1:
  3515 000049D3 C3                  <1> 	retn
  3516                              <1> 		; rts r0
  3517                              <1> 
  3518                              <1> namei:
  3519                              <1> 	; 15/05/2022
  3520                              <1> 	; 14/05/2022 (mounted directory path, '..' method)
  3521                              <1> 	; 03/02/2022
  3522                              <1> 	; 18/10/2015 (nbase, ncount)
  3523                              <1> 	; 12/10/2015
  3524                              <1> 	; 21/08/2015
  3525                              <1> 	; 18/07/2015
  3526                              <1> 	; 02/07/2015
  3527                              <1> 	; 17/06/2015
  3528                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3529                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3530                              <1> 	;
  3531                              <1> 	; 'namei' takes a file path name and returns i-number of
  3532                              <1> 	; the file in the current directory or the root directory
  3533                              <1> 	; (if the first character of the pathname is '/').	
  3534                              <1> 	;
  3535                              <1> 	; INPUTS ->
  3536                              <1> 	;    u.namep - points to a file path name
  3537                              <1> 	;    u.cdir - i-number of users directory
  3538                              <1> 	;    u.cdev - device number on which user directory resides	
  3539                              <1> 	; OUTPUTS ->
  3540                              <1> 	;    r1 - i-number of file
  3541                              <1> 	;    cdev
  3542                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3543                              <1> 	;               occurs in the search for file path name.
  3544                              <1> 	;	        If no match u.dirb points to the end of 
  3545                              <1> 	;               the directory and r1 = i-number of the current
  3546                              <1> 	;	        directory.	
  3547                              <1> 	; ((AX = R1))
  3548                              <1> 	;
  3549                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3550                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3551                              <1> 	;
  3552                              <1> 
  3553 000049D4 66A1[60700000]      <1> 	mov	ax, [u.cdir]
  3554                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3555                              <1> 			      ; / in r1
  3556 000049DA 668B15[A0700000]    <1> 	mov	dx, [u.cdrv]
  3557 000049E1 668915[40700000]    <1> 	mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3558                              <1> 				    ; device/drive number is in 1 byte, 
  3559                              <1> 				    ; not in 1 word!
  3560                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3561                              <1> 				; / into cdev
  3562                              <1> 	; 12/10/2015
  3563                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3564                              <1>       	 ; convert virtual (pathname) addr to physical address
  3565 000049E8 E869010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3566                              <1> 		; esi = physical address of [u.namep]
  3567                              <1> 		; ecx = byte count in the page
  3568 000049ED 803E2F              <1> 	cmp	byte [esi], '/'
  3569                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3570 000049F0 751D                <1> 	jne	short namei_1
  3571                              <1> 		; bne 1f
  3572 000049F2 FF05[74700000]      <1> 	inc	dword [u.namep]
  3573                              <1> 		; inc u.namep / go to next char
  3574                              <1> 	; 03/02/2022
  3575 000049F8 49                  <1> 	dec	ecx
  3576                              <1> 	;dec	cx ; remain byte count in the page
  3577 000049F9 7506                <1> 	jnz	short namei_0
  3578                              <1> 	; 12/10/2015
  3579 000049FB E856010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3580                              <1> 		; esi = physical address (page start + offset)
  3581                              <1> 		; ecx = byte count in the page
  3582 00004A00 4E                  <1> 	dec	esi
  3583                              <1> namei_0:
  3584 00004A01 46                  <1> 	inc 	esi  ; go to next char
  3585 00004A02 66A1[4C700000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3586                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3587 00004A08 C605[40700000]00    <1> 	mov	byte [cdev], 0
  3588                              <1> 		; clr cdev / clear device number
  3589                              <1> namei_1: ; 1:
  3590 00004A0F F606FF              <1> 	test	byte [esi], 0FFh
  3591                              <1> namei_10: ; 03/02/2022 (jump from namei_8)
  3592 00004A12 74BF                <1> 	jz	short getf4
  3593                              <1> 	;jz	nig
  3594                              <1> 		; tstb *u.namep / is the character in file name a nul
  3595                              <1> 		; beq nig / yes, end of file name reached; 
  3596                              <1> 			; / branch to "nig"
  3597                              <1> namei_2: ; 1:
  3598                              <1> 	; 18/10/2015
  3599 00004A14 8935[CC700000]      <1> 	mov 	[nbase], esi
  3600 00004A1A 66890D[D0700000]    <1> 	mov 	[ncount], cx
  3601                              <1> 	;
  3602                              <1> 	;mov	dx, 2
  3603 00004A21 B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3604 00004A23 E895080000          <1> 	call	access
  3605                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3606                              <1> 	; 'access' will not return here if user has not "r" permission !
  3607                              <1> 	; 03/02/2022
  3608 00004A28 F605[596D0000]40    <1> 	test	byte [i.flgs+1], 40h
  3609                              <1> 	;test 	word [i.flgs], 4000h
  3610                              <1> 		; bit $40000,i.flgs / directory i-node?
  3611 00004A2F 746A                <1>         jz      short namei_err
  3612                              <1> 		; beq error3 / no, got an error
  3613                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3614 00004A31 31C0                <1> 	xor	eax, eax
  3615 00004A33 A3[78700000]        <1> 	mov	[u.off], eax ; 0
  3616 00004A38 66A1[5C6D0000]      <1> 	mov	ax, [i.size]
  3617 00004A3E A3[70700000]        <1> 	mov	[u.dirp], eax
  3618                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3619                              <1> 		; clr u.off / u.off is file offset used by user
  3620 00004A43 C705[6C700000]-     <1> 	mov	dword [u.fofp], u.off
  3620 00004A49 [78700000]          <1>
  3621                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3622                              <1> 				  ; / the offset portion of fsp entry
  3623                              <1> namei_3: ; 2:
  3624 00004A4D C705[7C700000]-     <1> 	mov	dword [u.base], u.dirbuf
  3624 00004A53 [8E700000]          <1>
  3625                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3626                              <1> 				    ; / copied from a directory
  3627 00004A57 C705[80700000]0A00- <1> 	mov 	dword [u.count], 10 	
  3627 00004A5F 0000                <1>
  3628                              <1>  		; mov $10.,u.count / u.count is byte count 
  3629                              <1> 				 ; / for reads and writes
  3630 00004A61 66A1[3C700000]      <1> 	mov 	ax, [ii]
  3631                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3632 00004A67 FE05[BD700000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3633 00004A6D E84B090000          <1>     	call	readi
  3634                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3635                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3636 00004A72 8B0D[84700000]      <1> 	mov 	ecx, [u.nread]
  3637 00004A78 09C9                <1> 	or 	ecx, ecx
  3638                              <1> 		; tst u.nread
  3639 00004A7A 741B                <1> 	jz	short nib
  3640                              <1> 		; ble nib / gives error return
  3641                              <1> 	;
  3642 00004A7C 668B1D[8E700000]    <1> 	mov 	bx, [u.dirbuf]
  3643 00004A83 6621DB              <1> 	and 	bx, bx       
  3644                              <1> 		; tst u.dirbuf /
  3645 00004A86 7522                <1> 	jnz	short namei_4
  3646                              <1> 		; bne 3f / branch when active directory entry 
  3647                              <1> 		       ; / (i-node word in entry non zero)
  3648 00004A88 A1[78700000]        <1> 	mov	eax, [u.off]
  3649 00004A8D 83E80A              <1> 	sub	eax, 10
  3650 00004A90 A3[70700000]        <1> 	mov	[u.dirp], eax
  3651                              <1> 		; mov u.off,u.dirp
  3652                              <1> 		; sub $10.,u.dirp
  3653 00004A95 EBB6                <1> 	jmp	short namei_3
  3654                              <1> 		; br 2b
  3655                              <1> 
  3656                              <1> 	; 18/07/2013
  3657                              <1> nib: 
  3658 00004A97 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3659 00004A99 F9                  <1> 	stc
  3660                              <1> nig:
  3661 00004A9A C3                  <1> 	retn
  3662                              <1> 
  3663                              <1> namei_err:
  3664                              <1> 	; 16/06/2015
  3665 00004A9B C705[AB700000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3665 00004AA3 0000                <1>
  3666 00004AA5 E929F0FFFF          <1> 	jmp	error
  3667                              <1> 
  3668                              <1> namei_4: ; 3:
  3669                              <1> 	; 18/10/2015
  3670                              <1> 	; 12/10/2015
  3671                              <1> 	; 21/08/2015
  3672                              <1> 	; 18/07/2015
  3673 00004AAA 8B2D[74700000]      <1> 	mov	ebp, [u.namep]
  3674                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3675 00004AB0 BF[90700000]        <1> 	mov 	edi, u.dirbuf + 2
  3676                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3677                              <1> 	; 18/10/2015
  3678 00004AB5 8B35[CC700000]      <1> 	mov	esi, [nbase]	
  3679 00004ABB 668B0D[D0700000]    <1> 	mov	cx, [ncount]
  3680                              <1> 	;
  3681 00004AC2 6621C9              <1> 	and	cx, cx
  3682 00004AC5 7505                <1> 	jnz	short namei_5	
  3683                              <1> 	;
  3684 00004AC7 E890000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3685                              <1> 		; esi = physical address (page start + offset)
  3686                              <1> 		; ecx = byte count in the page
  3687                              <1> namei_5: ; 3:
  3688 00004ACC 45                  <1> 	inc	ebp ; 18/07/2015
  3689 00004ACD AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3690                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3691 00004ACE 08C0                <1> 	or 	al, al
  3692 00004AD0 741C                <1> 	jz 	short namei_7
  3693                              <1> 		; beq 3f / if char is nul, then the last char in string
  3694                              <1> 			; / has been moved
  3695 00004AD2 3C2F                <1> 	cmp	al, '/'
  3696                              <1> 		; cmp r4,$'/ / is char a </>
  3697 00004AD4 7418                <1> 	je 	short namei_7
  3698                              <1> 		; beq 3f
  3699                              <1> 	; 03/02/2022
  3700 00004AD6 49                  <1> 	dec	ecx	
  3701                              <1> 	; 12/10/2015
  3702                              <1> 	;dec	cx ; remain byte count in the page
  3703 00004AD7 7505                <1> 	jnz	short namei_6
  3704 00004AD9 E87E000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3705                              <1> 		; esi = physical address (page start + offset)
  3706                              <1> 		; ecx = byte count in the page
  3707                              <1> namei_6:
  3708 00004ADE 81FF[98700000]      <1>         cmp     edi, u.dirbuf + 10
  3709                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3710                              <1> 				     ; / all 8 bytes of file name
  3711 00004AE4 74E6                <1> 	je	short namei_5
  3712                              <1> 		; beq 3b
  3713 00004AE6 AE                  <1> 	scasb	
  3714                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3715                              <1> 			      ; / char read from directory
  3716 00004AE7 74E3                <1> 	je 	short namei_5
  3717                              <1> 		; beq 3b / branch if chars match
  3718                              <1> namei_9:
  3719 00004AE9 E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3720                              <1> 		; br 2b / file names do not match go to next directory entry
  3721                              <1> namei_7: ; 3:
  3722 00004AEE 81FF[98700000]      <1> 	cmp	edi, u.dirbuf + 10
  3723                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3724 00004AF4 7406                <1> 	je	short namei_8
  3725                              <1> 		; beq 3f
  3726 00004AF6 8A27                <1> 	mov 	ah, [edi]
  3727                              <1> 	;inc 	edi 
  3728 00004AF8 20E4                <1> 	and 	ah, ah
  3729                              <1> 		; tstb (r3)+ /
  3730                              <1>         ;jnz	namei_3
  3731                              <1> 		; bne 2b
  3732                              <1> 	; 03/02/2020
  3733 00004AFA 75ED                <1> 	jnz	short namei_9
  3734                              <1> namei_8: ; 3
  3735 00004AFC 892D[74700000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3736                              <1> 		; mov r2,u.namep / u.namep points to char 
  3737                              <1> 			       ; / following a / or nul
  3738                              <1> 	;mov	bx, [u.dirbuf]
  3739                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3740                              <1> 				; / entry to r1
  3741                              <1> 	;;;;
  3742                              <1> 	; 14/05/2022 - Retro UNIX (8086/386) feature only !
  3743                              <1> 	; ! 'pwd' utility modification !
  3744                              <1> 	; ((if directory entry name is a dotdot)))
  3745                              <1> 	;; check if it is mounted device's root directory inode
  3746                              <1> 	; and if so, replace it with parent dir inode number
  3747                              <1> 	;  of mounting directory in [mntp].
  3748                              <1> 
  3749 00004B02 668B1D[8E700000]    <1> 	mov	bx, [u.dirbuf]
  3750                              <1> 
  3751 00004B09 6683FB29            <1> 	cmp	bx, 41 ; root directory inode number
  3752 00004B0D 753C                <1> 	jne	short namei_11
  3753                              <1> 
  3754 00004B0F 663B1D[3C700000]    <1> 	cmp	bx, [ii] ; for root dir, '.' & '..' is 41
  3755 00004B16 7533                <1> 	jne	short namei_11 ; not root dir (of mounted dev)
  3756                              <1> 
  3757                              <1> 	;cmp	[idev], bh ; 0
  3758 00004B18 383D[40700000]      <1> 	cmp	[cdev], bh ; 0
  3759                              <1> 			; 0 = root fs, dev num in [rdev]
  3760                              <1> 			; 1 = mounted, dev num in [mdev]
  3761 00004B1E 762B                <1> 	jna	short namei_11
  3762                              <1> 
  3763                              <1> 	; dotdot (parent directory link) check
  3764 00004B20 66813D[90700000]2E- <1> 	cmp	word [u.dirbuf+2], '..'
  3764 00004B28 2E                  <1>
  3765 00004B29 7520                <1> 	jne	short namei_11
  3766 00004B2B 803D[92700000]00    <1> 	cmp	byte [u.dirbuf+4], 0
  3767 00004B32 7517                <1> 	jne	short namei_11
  3768                              <1> 	
  3769                              <1> 	; (This may not be necessary because [idev] = 1
  3770                              <1> 	; and [mnti] is expected as a sub dir inode number)
  3771 00004B34 66391D[46700000]    <1> 	cmp	[mnti], bx ; 41
  3772 00004B3B 760E                <1> 	jna	short namei_11
  3773                              <1> 	
  3774                              <1> 	; change inumber to parent dir inum of mount directory
  3775 00004B3D 668B1D[48700000]    <1> 	mov	bx, [mntp]
  3776 00004B44 C605[40700000]00    <1> 	mov	byte [cdev], 0 ; root fs
  3777                              <1> namei_11:
  3778                              <1> 	;;;;
  3779                              <1> 
  3780 00004B4B 20C0                <1> 	and 	al, al
  3781                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3782                              <1> 		      ;  / if r4 = </> then go to next directory
  3783                              <1> 	; 15/05/2022
  3784 00004B4D 6689D8              <1> 	mov	ax, bx
  3785                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  3786                              <1>   	; 03/02/2022
  3787 00004B50 E9BDFEFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3788                              <1> 	;jnz	namei_2 
  3789                              <1> 		; bne 1b
  3790                              <1> 	; AX = i-number of the file
  3791                              <1> ;;nig:
  3792 00004B55 C3                  <1> 	retn
  3793                              <1> 		; tst (r0)+ / gives non-error return
  3794                              <1> ;;nib:
  3795                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3796                              <1> 		       ; ax = 0 -> file not found 
  3797                              <1> ;;	stc	; 27/05/2013
  3798                              <1> ;;	retn
  3799                              <1> 		; rts r0
  3800                              <1> 
  3801                              <1> trans_addr_nmbp:
  3802                              <1> 	; 03/02/2022
  3803                              <1> 	; 18/10/2015
  3804                              <1> 	; 12/10/2015
  3805 00004B56 8B2D[74700000]      <1> 	mov 	ebp, [u.namep]
  3806                              <1> trans_addr_nm:
  3807                              <1> 	; 03/02/2022
  3808                              <1> 	; Convert virtual (pathname) address to physical address
  3809                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3810                              <1> 	; 18/10/2015
  3811                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3812                              <1> 	; 02/07/2015
  3813                              <1> 	; 17/06/2015
  3814                              <1> 	; 16/06/2015
  3815                              <1> 	;
  3816                              <1> 	; INPUTS: 
  3817                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3818                              <1> 	;	[u.pgdir] = user's page directory
  3819                              <1> 	; OUTPUT:
  3820                              <1> 	;       esi = physical address of the pathname
  3821                              <1> 	;	ecx = remain byte count in the page
  3822                              <1> 	;
  3823                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3824                              <1> 	;
  3825                              <1> 
  3826                              <1> 	; 03/02/2022
  3827 00004B5C 29C9                <1> 	sub	ecx, ecx
  3828                              <1> 
  3829 00004B5E 833D[B3700000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3830 00004B65 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3831                              <1> 				     ; it is already physical address
  3832 00004B67 50                  <1>    	push	eax	
  3833 00004B68 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3834 00004B6A E849E6FFFF          <1>        	call	get_physical_addr ; get physical address
  3835 00004B6F 7204                <1> 	jc	short tr_addr_nm_err
  3836                              <1> 	; 18/10/2015
  3837                              <1> 	; eax = physical address 
  3838                              <1> 	; cx = remain byte count in page (1-4096) 
  3839                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3840 00004B71 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3841 00004B73 58                  <1> 	pop	eax 
  3842 00004B74 C3                  <1> 	retn
  3843                              <1> 
  3844                              <1> tr_addr_nm_err:
  3845 00004B75 A3[AB700000]        <1> 	mov	[u.error], eax
  3846                              <1> 	;pop 	eax
  3847 00004B7A E954EFFFFF          <1> 	jmp	error
  3848                              <1> 
  3849                              <1> trans_addr_nmk:
  3850                              <1> 	; 12/10/2015
  3851                              <1> 	; 02/07/2015
  3852 00004B7F 8B35[74700000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3853                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3854                              <1> 	; 03/02/2022
  3855 00004B85 B510                <1> 	mov	ch, PAGE_SIZE/256
  3856 00004B87 C3                  <1> 	retn
  3857                              <1> 
  3858                              <1> syschdir:
  3859                              <1> 	; 03/02/2022
  3860                              <1> 	; / makes the directory specified in the argument
  3861                              <1> 	; / the current directory
  3862                              <1> 	;
  3863                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3864                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3865                              <1> 	;
  3866                              <1> 	; 'syschdir' makes the directory specified in its argument
  3867                              <1> 	; the current working directory.
  3868                              <1> 	;
  3869                              <1> 	; Calling sequence:
  3870                              <1> 	;	syschdir; name
  3871                              <1> 	; Arguments:
  3872                              <1> 	;	name - address of the path name of a directory
  3873                              <1> 	;	       terminated by nul byte.	
  3874                              <1> 	; Inputs: -
  3875                              <1> 	; Outputs: -
  3876                              <1> 	; ...............................................................
  3877                              <1> 	;				
  3878                              <1> 	; Retro UNIX 8086 v1 modification:
  3879                              <1> 	;	 The user/application program puts address of 
  3880                              <1> 	;	 the path name in BX register as 'syschdir' 
  3881                              <1> 	; 	 system call argument.
  3882                              <1> 
  3883 00004B88 891D[74700000]      <1> 	mov	[u.namep], ebx
  3884                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  3885 00004B8E E841FEFFFF          <1> 	call	namei
  3886                              <1> 		; jsr r0,namei / find its i-number
  3887                              <1> 	;jc	error
  3888                              <1> 		; br error3
  3889 00004B93 730F                <1> 	jnc	short syschdir0
  3890                              <1> 	; 'directory not found !' error
  3891 00004B95 C705[AB700000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3891 00004B9D 0000                <1>
  3892 00004B9F E92FEFFFFF          <1> 	jmp	error
  3893                              <1> syschdir0:
  3894                              <1> 	; 03/02/2022
  3895 00004BA4 B202                <1> 	mov	dl, 2  ; read access ; 03/02/2022 (BugFix)
  3896 00004BA6 E812070000          <1> 	call	access
  3897                              <1> 		; jsr r0,access; 2 / get i-node into core
  3898                              <1> 	; 03/02/2022
  3899 00004BAB F605[596D0000]40    <1> 	test	byte [i.flgs+1], 40h
  3900                              <1> 	;test	word [i.flgs], 4000h
  3901                              <1> 		; bit $40000,i.flgs / is it a directory?
  3902                              <1> 	;jz	error 
  3903                              <1> 		; beq error3 / no error
  3904 00004BB2 750F                <1> 	jnz	short syschdir1
  3905 00004BB4 C705[AB700000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3905 00004BBC 0000                <1>
  3906 00004BBE E910EFFFFF          <1> 	jmp	error
  3907                              <1> syschdir1:
  3908 00004BC3 66A3[60700000]      <1> 	mov	[u.cdir], ax
  3909                              <1> 		; mov r1,u.cdir / move i-number to users 
  3910                              <1> 			      ; / current directory
  3911 00004BC9 66A1[40700000]      <1> 	mov	ax, [cdev]
  3912 00004BCF 66A3[A0700000]      <1> 	mov	[u.cdrv], ax
  3913                              <1> 		; mov cdev,u.cdev / move its device to users 
  3914                              <1> 			        ; / current device
  3915 00004BD5 E919EFFFFF          <1> 	jmp	sysret
  3916                              <1> 		; br sysret3
  3917                              <1> 	
  3918                              <1> syschmod: ; < change mode of file >
  3919                              <1> 	; 29/04/2022 (bugfix)
  3920                              <1> 	; 03/02/2022
  3921                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3922                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3923                              <1> 	;
  3924                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  3925                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  3926                              <1> 	; changed to 'mode'.
  3927                              <1> 	;
  3928                              <1> 	; Calling sequence:
  3929                              <1> 	;	syschmod; name; mode
  3930                              <1> 	; Arguments:
  3931                              <1> 	;	name - address of the file name
  3932                              <1> 	;	       terminated by null byte.
  3933                              <1> 	;	mode - (new) mode/flags < attributes >
  3934                              <1> 	;	
  3935                              <1> 	; Inputs: -
  3936                              <1> 	; Outputs: -
  3937                              <1> 	; ...............................................................
  3938                              <1> 	;				
  3939                              <1> 	; Retro UNIX 8086 v1 modification: 
  3940                              <1> 	;       'syschmod' system call has two arguments; so,
  3941                              <1> 	;	* 1st argument, name is pointed to by BX register
  3942                              <1> 	;	* 2nd argument, mode is in CX register
  3943                              <1> 	;
  3944                              <1> 	; Mode bits (Flags):
  3945                              <1> 	;	bit 0 - write permission for non-owner (1)
  3946                              <1> 	;	bit 1 - read permission for non-owner (2)
  3947                              <1> 	;	bit 2 - write permission for owner (4)
  3948                              <1> 	;	bit 3 - read permission for owner (8)
  3949                              <1> 	;	bit 4 - executable flag (16) 	
  3950                              <1> 	;	bit 5 - set user ID on execution flag (32) 
  3951                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  3952                              <1> 	;	bit 12 - large file flag (4096)
  3953                              <1> 	;	bit 13 - file has modified flag (always on) (8192)
  3954                              <1> 	;	bit 14 - directory flag (16384)
  3955                              <1> 	;	bit 15 - 'i-node is allocated' flag (32768)
  3956                              <1> 
  3957                              <1> 	; / name; mode
  3958 00004BDA E815000000          <1> 	call	isown
  3959                              <1> 		;jsr r0,isown / get the i-node and check user status
  3960                              <1> 	; 03/02/2022
  3961 00004BDF F605[596D0000]40    <1> 	test	byte [i.flgs+1], 40h
  3962                              <1> 	;test	word [i.flgs], 4000h
  3963                              <1> 		; bit $40000,i.flgs / directory?
  3964 00004BE6 7402                <1> 	jz	short syschmod1
  3965                              <1> 		; beq 2f / no
  3966                              <1> 	; AL = (new) mode
  3967 00004BE8 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  3968                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  3969                              <1> 			   ; / executable modes
  3970                              <1> syschmod1: ; 2:
  3971 00004BEA A2[586D0000]        <1> 	mov	[i.flgs], al	
  3972                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  3973                              <1> 	;jmp	short isown1
  3974                              <1> 	;	; br 1f ; (jmp sysret4)
  3975                              <1> 	; 29/04/2022
  3976 00004BEF E9FFEEFFFF          <1> 	jmp	sysret
  3977                              <1> 
  3978                              <1> isown:
  3979                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  3980                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3981                              <1> 	;
  3982                              <1> 	; 'isown' is given a file name (the 1st argument).
  3983                              <1> 	;  It find the i-number of that file via 'namei' 
  3984                              <1> 	;  then gets the i-node into core via 'iget'.
  3985                              <1> 	;  It then tests to see if the user is super user. 
  3986                              <1> 	;  If not, it cheks to see if the user is owner of 
  3987                              <1> 	;  the file. If he is not an error occurs.
  3988                              <1> 	;  If user is the owner 'setimod' is called to indicate
  3989                              <1> 	;  the inode has been modificed and the 2nd argument of
  3990                              <1> 	;  the call is put in r2.
  3991                              <1> 	;
  3992                              <1> 	; INPUTS ->
  3993                              <1> 	;    arguments of syschmod and syschown calls
  3994                              <1> 	; OUTPUTS ->
  3995                              <1> 	;    u.uid - id of user
  3996                              <1> 	;    imod - set to a 1
  3997                              <1> 	;    r2 - contains second argument of the system call				 	
  3998                              <1> 	;
  3999                              <1> 	;   ((AX=R2) output as 2nd argument)
  4000                              <1> 	;
  4001                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4002                              <1> 	;
  4003                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4004                              <1> 	;; ! 2nd argument on top of stack !
  4005                              <1> 	;; 22/06/2015 - 32 bit modifications
  4006                              <1> 	;; 07/07/2013
  4007 00004BF4 891D[74700000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4008 00004BFA 51                  <1> 	push 	ecx ;; 2nd argument
  4009                              <1> 	;;
  4010 00004BFB E8D4FDFFFF          <1> 	call	namei
  4011                              <1> 		; jsr r0,namei / get its i-number
  4012                              <1>        ; Retro UNIX 8086 v1 modification !
  4013                              <1>        ; ax = 0 -> file not found 
  4014                              <1> 	;and	ax, ax
  4015                              <1> 	;jz	error
  4016                              <1> 	;jc	error ; 27/05/2013
  4017                              <1> 		; br error3
  4018 00004C00 730F                <1> 	jnc	short isown0
  4019                              <1> 	; 'file not found !' error
  4020 00004C02 C705[AB700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4020 00004C0A 0000                <1>
  4021 00004C0C E9C2EEFFFF          <1> 	jmp	error
  4022                              <1> isown0:
  4023 00004C11 E8D3050000          <1> 	call	iget
  4024                              <1> 		; jsr r0,iget / get i-node into core
  4025 00004C16 A0[A2700000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4026 00004C1B 08C0                <1> 	or	al, al
  4027                              <1> 		; tstb u.uid / super user?
  4028 00004C1D 7417                <1> 	jz	short isown1
  4029                              <1> 		; beq 1f / yes, branch
  4030 00004C1F 3A05[5B6D0000]      <1> 	cmp	al, [i.uid]
  4031                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4032                              <1> 				 ; / the file
  4033                              <1> 	;jne	error
  4034                              <1> 		; beq 1f / yes
  4035                              <1> 		; jmp error3 / no, error
  4036 00004C25 740F                <1> 	je	short isown1
  4037                              <1> 
  4038 00004C27 C705[AB700000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4038 00004C2F 0000                <1>
  4039                              <1> 			;  'permission denied !' error
  4040 00004C31 E99DEEFFFF          <1> 	jmp	error
  4041                              <1> isown1: ; 1:
  4042 00004C36 E8B8060000          <1> 	call	setimod
  4043                              <1> 		; jsr r0,setimod / indicates 
  4044                              <1> 		;	       ; / i-node has been modified
  4045 00004C3B 58                  <1> 	pop	eax ; 2nd argument
  4046                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4047                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4048 00004C3C C3                  <1> 	retn
  4049                              <1> 		; rts r0
  4050                              <1> 
  4051                              <1> ;;arg:  ; < get system call arguments >
  4052                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4053                              <1> 	; of form:
  4054                              <1> 	;	sys 'routine' ; arg1
  4055                              <1> 	;		or
  4056                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4057                              <1> 	;		or
  4058                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4059                              <1> 	;	
  4060                              <1> 	; INPUTS ->
  4061                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4062                              <1> 	;	This pointers's value is actually the value of
  4063                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4064                              <1> 	;	made to process the sys instruction
  4065                              <1> 	;    r0 - contains the return address for the routine
  4066                              <1> 	;	that called arg. The data in the word pointer 
  4067                              <1> 	;	to by the return address is used as address
  4068                              <1> 	;	in which the extracted argument is stored   		
  4069                              <1> 	;    	
  4070                              <1> 	; OUTPUTS ->
  4071                              <1> 	;    'address' - contains the extracted argument 
  4072                              <1> 	;    u.sp+18 - is incremented by 2 
  4073                              <1> 	;    r1 - contains the extracted argument
  4074                              <1> 	;    r0 - points to the next instruction to be
  4075                              <1> 	;	 executed in the calling routine.
  4076                              <1> 	;
  4077                              <1>   
  4078                              <1> 	; mov u.sp,r1
  4079                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4080                              <1> 			; / into argument of arg2
  4081                              <1> 	; add $2,18.(r1) / point pc on stack 
  4082                              <1> 			      ; / to next system argument
  4083                              <1> 	; rts r0
  4084                              <1> 
  4085                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4086                              <1> 	; 'arg2' takes first argument in system call
  4087                              <1> 	;  (pointer to name of the file) and puts it in location
  4088                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4089                              <1> 	;  and on top of the stack
  4090                              <1> 	;	
  4091                              <1> 	; INPUTS ->
  4092                              <1> 	;    u.sp, r0
  4093                              <1> 	;    	
  4094                              <1> 	; OUTPUTS ->
  4095                              <1> 	;    u.namep
  4096                              <1> 	;    u.off 
  4097                              <1> 	;    u.off pushed on stack
  4098                              <1> 	;    r1
  4099                              <1> 	;
  4100                              <1> 
  4101                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4102                              <1> 				; / first arg in sys call
  4103                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4104                              <1> 				; / second arg in sys call
  4105                              <1> 	; mov r0,r1 / r0 points to calling routine
  4106                              <1> 	; mov (sp),r0 / put operation code back in r0
  4107                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4108                              <1> 			; / on stack
  4109                              <1> 	; jmp (r1) / return to calling routine
  4110                              <1> 
  4111                              <1> syschown: ; < change owner of file >
  4112                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4113                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4114                              <1> 	;
  4115                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4116                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4117                              <1> 	; changed to 'owner'
  4118                              <1> 	;
  4119                              <1> 	; Calling sequence:
  4120                              <1> 	;	syschown; name; owner
  4121                              <1> 	; Arguments:
  4122                              <1> 	;	name - address of the file name
  4123                              <1> 	;	       terminated by null byte.
  4124                              <1> 	;	owner - (new) owner (number/ID)
  4125                              <1> 	;	
  4126                              <1> 	; Inputs: -
  4127                              <1> 	; Outputs: -
  4128                              <1> 	; ...............................................................
  4129                              <1> 	;				
  4130                              <1> 	; Retro UNIX 8086 v1 modification: 
  4131                              <1> 	;       'syschown' system call has two arguments; so,
  4132                              <1> 	;	* 1st argument, name is pointed to by BX register
  4133                              <1> 	;	* 2nd argument, owner number is in CX register
  4134                              <1> 	;
  4135                              <1> 	; / name; owner
  4136 00004C3D E8B2FFFFFF          <1> 	call	isown
  4137                              <1> 		; jsr r0,isown / get the i-node and check user status
  4138 00004C42 803D[A2700000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4139                              <1> 		; tstb u.uid / super user
  4140 00004C49 7418                <1> 	jz	short syschown1
  4141                              <1> 		; beq 2f / yes, 2f
  4142 00004C4B F605[586D0000]20    <1>         test    byte [i.flgs], 20h ; 32
  4143                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4144                              <1> 	;jnz	error
  4145                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4146 00004C52 740F                <1> 	jz	short syschown1
  4147                              <1> 	; 'permission denied !'
  4148 00004C54 C705[AB700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4148 00004C5C 0000                <1>
  4149 00004C5E E970EEFFFF          <1> 	jmp	error
  4150                              <1> syschown1: ; 2:
  4151                              <1> 	; AL = owner (number/ID)
  4152 00004C63 A2[5B6D0000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4153                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4154                              <1> 			       ; / in the i-node
  4155 00004C68 E986EEFFFF          <1> 	jmp	sysret
  4156                              <1> 	; 1: 
  4157                              <1> 		; jmp sysret4
  4158                              <1> 	; 3:
  4159                              <1> 		; jmp	error
  4160                              <1> 
  4161                              <1> systime: ; / get time of year
  4162                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4163                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4164                              <1> 	;
  4165                              <1> 	; 20/06/2013
  4166                              <1> 	; 'systime' gets the time of the year.
  4167                              <1> 	; The present time is put on the stack.
  4168                              <1> 	;
  4169                              <1> 	; Calling sequence:
  4170                              <1> 	;	systime
  4171                              <1> 	; Arguments: -
  4172                              <1> 	;	
  4173                              <1> 	; Inputs: -
  4174                              <1> 	; Outputs: sp+2, sp+4 - present time
  4175                              <1> 	; ...............................................................
  4176                              <1> 	;	
  4177                              <1> 	; Retro UNIX 8086 v1 modification: 
  4178                              <1> 	;       'systime' system call will return to the user
  4179                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4180                              <1> 	;
  4181                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4182                              <1> 	;	system call for PC compatibility !!		 	
  4183                              <1> 
  4184 00004C6D E8AFE9FFFF          <1> 	call 	epoch
  4185 00004C72 A3[5C700000]        <1> 	mov 	[u.r0], eax
  4186                              <1> 		; mov s.time,4(sp)
  4187                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4188                              <1> 				   ; / on the stack
  4189                              <1> 		; br sysret4
  4190 00004C77 E977EEFFFF          <1> 	jmp	sysret 
  4191                              <1> 
  4192                              <1> sysstime: ; / set time
  4193                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4194                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4195                              <1> 	;
  4196                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4197                              <1> 	;
  4198                              <1> 	; Calling sequence:
  4199                              <1> 	;	sysstime
  4200                              <1> 	; Arguments: -
  4201                              <1> 	;	
  4202                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4203                              <1> 	; Outputs: -
  4204                              <1> 	; ...............................................................
  4205                              <1> 	;	
  4206                              <1> 	; Retro UNIX 8086 v1 modification: 
  4207                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4208                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4209                              <1> 	; 
  4210                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4211                              <1> 	;	to get sysstime system call arguments from the user;
  4212                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4213                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4214                              <1> 	;
  4215                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4216                              <1> 	;	system call for PC compatibility !!	
  4217                              <1> 
  4218 00004C7C 803D[A2700000]00    <1> 	cmp	byte [u.uid], 0
  4219                              <1> 		; tstb u.uid / is user the super user
  4220                              <1> 	;ja	error
  4221                              <1> 		; bne error4 / no, error
  4222 00004C83 760F                <1> 	jna	short systime1
  4223                              <1> 	; 'permission denied !'
  4224 00004C85 C705[AB700000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4224 00004C8D 0000                <1>
  4225 00004C8F E93FEEFFFF          <1> 	jmp	error
  4226                              <1> systime1:
  4227                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4228                              <1> 	; EBX = unix (epoch) time (from user)
  4229 00004C94 89D8                <1> 	mov	eax, ebx
  4230 00004C96 E806EBFFFF          <1> 	call 	set_date_time
  4231                              <1> 		; mov 4(sp),s.time
  4232                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4233 00004C9B E953EEFFFF          <1> 	jmp	sysret
  4234                              <1> 		; br sysret4
  4235                              <1> 
  4236                              <1> sysbreak:
  4237                              <1> 	; 18/10/2015
  4238                              <1> 	; 07/10/2015
  4239                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4240                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4241                              <1> 	;
  4242                              <1> 	; 'sysbreak' sets the programs break points. 
  4243                              <1> 	; It checks the current break point (u.break) to see if it is
  4244                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4245                              <1> 	; even address (if it was odd) and the area between u.break
  4246                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4247                              <1> 	; in u.break and control is passed to 'sysret'.
  4248                              <1> 	;
  4249                              <1> 	; Calling sequence:
  4250                              <1> 	;	sysbreak; addr
  4251                              <1> 	; Arguments: -
  4252                              <1> 	;	
  4253                              <1> 	; Inputs: u.break - current breakpoint
  4254                              <1> 	; Outputs: u.break - new breakpoint 
  4255                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4256                              <1> 	; ...............................................................
  4257                              <1> 	;	
  4258                              <1> 	; Retro UNIX 8086 v1 modification:
  4259                              <1> 	;	The user/application program puts breakpoint address
  4260                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4261                              <1> 	; 	(argument transfer method 1)
  4262                              <1> 	;
  4263                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4264                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4265                              <1> 	;  NOTE:
  4266                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4267                              <1> 	;	'u.break' address) of user's memory for original unix's
  4268                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4269                              <1> 
  4270                              <1> 		; mov u.break,r1 / move users break point to r1
  4271                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4272                              <1> 		; blos 1f / yes, 1f
  4273                              <1> 	; 23/06/2015
  4274 00004CA0 8B2D[88700000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4275                              <1> 	;and	ebp, ebp
  4276                              <1> 	;jz	short sysbreak_3 
  4277                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4278                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4279 00004CA6 8B15[54700000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4280 00004CAC 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4281                              <1> 	; 07/10/2015
  4282 00004CAF 891D[88700000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4283                              <1> 	;
  4284 00004CB5 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4285                              <1> 			   ; with top of user's stack (virtual!)
  4286 00004CB7 7327                <1> 	jnb	short sysbreak_3
  4287                              <1> 		; cmp r1,sp / is it the same or higher 
  4288                              <1> 			  ; / than the stack?
  4289                              <1> 		; bhis 1f / yes, 1f
  4290 00004CB9 89DE                <1> 	mov	esi, ebx
  4291 00004CBB 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4292 00004CBD 7621                <1> 	jna	short sysbreak_3 
  4293                              <1> 	;push	ebx
  4294                              <1> sysbreak_1:
  4295 00004CBF 89EB                <1> 	mov	ebx, ebp  
  4296 00004CC1 E8F2E4FFFF          <1> 	call	get_physical_addr ; get physical address
  4297 00004CC6 0F82A9FEFFFF        <1> 	jc	tr_addr_nm_err
  4298                              <1> 	; 18/10/2015
  4299 00004CCC 89C7                <1> 	mov	edi, eax 
  4300 00004CCE 29C0                <1> 	sub	eax, eax ; 0
  4301                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4302 00004CD0 39CE                <1> 	cmp	esi, ecx
  4303 00004CD2 7302                <1> 	jnb	short sysbreak_2
  4304 00004CD4 89F1                <1> 	mov	ecx, esi
  4305                              <1> sysbreak_2:
  4306 00004CD6 29CE                <1> 	sub	esi, ecx
  4307 00004CD8 01CD                <1> 	add	ebp, ecx
  4308 00004CDA F3AA                <1> 	rep 	stosb
  4309 00004CDC 09F6                <1> 	or	esi, esi
  4310 00004CDE 75DF                <1> 	jnz	short sysbreak_1
  4311                              <1> 	;
  4312                              <1> 		; bit $1,r1 / is it an odd address
  4313                              <1> 		; beq 2f / no, its even
  4314                              <1> 		; clrb (r1)+ / yes, make it even
  4315                              <1> 	; 2: / clear area between the break point and the stack
  4316                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4317                              <1> 		; bhis 1f / yes, quit
  4318                              <1> 		; clr (r1)+ / clear word
  4319                              <1> 		; br 2b / go back
  4320                              <1> 	;pop	ebx
  4321                              <1> sysbreak_3: ; 1:
  4322                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4323                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4324                              <1> 			; / in u.break (set new break point)
  4325                              <1> 		; br sysret4 / br sysret
  4326 00004CE0 E90EEEFFFF          <1> 	jmp	sysret
  4327                              <1> 
  4328                              <1> maknod: 
  4329                              <1> 	; 12/02/2022
  4330                              <1> 	; 03/02/2022
  4331                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4332                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4333                              <1> 	;
  4334                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4335                              <1> 	; for this i-node in the current directory.
  4336                              <1> 	;
  4337                              <1> 	; INPUTS ->
  4338                              <1> 	;    r1 - contains mode
  4339                              <1> 	;    ii - current directory's i-number	
  4340                              <1> 	;    	
  4341                              <1> 	; OUTPUTS ->
  4342                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4343                              <1> 	;    i.flgs - flags in new i-node 
  4344                              <1> 	;    i.uid - filled with u.uid
  4345                              <1> 	;    i.nlks - 1 is put in the number of links
  4346                              <1> 	;    i.ctim - creation time				
  4347                              <1> 	;    i.ctim+2 - modification time
  4348                              <1> 	;    imod - set via call to setimod
  4349                              <1> 	;	
  4350                              <1> 	; ((AX = R1)) input
  4351                              <1> 	;
  4352                              <1> 	; (Retro UNIX Prototype : 
  4353                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4354                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4355                              <1> 
  4356                              <1> 	; / r1 contains the mode
  4357 00004CE5 80CC80              <1> 	or 	ah, 80h ; 10000000b
  4358                              <1> 		; bis $100000,r1 / allocate flag set
  4359 00004CE8 6650                <1> 	push	ax ; *
  4360                              <1> 		; mov r1,-(sp) / put mode on stack
  4361                              <1> 	; 31/07/2013
  4362 00004CEA 66A1[3C700000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4363                              <1> 		; mov ii,r1 / move current i-number to r1
  4364 00004CF0 B201                <1> 	mov	dl, 1 ; owner flag mask
  4365 00004CF2 E8C6050000          <1> 	call	access	
  4366                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4367                              <1> 	; 03/02/2022
  4368 00004CF7 50                  <1> 	push	eax ; **
  4369                              <1> 	;push	ax
  4370                              <1> 		; mov r1,-(sp) / put i-number on stack
  4371 00004CF8 66B82800            <1> 	mov	ax, 40
  4372                              <1> 		; mov $40.,r1 / r1 = 40
  4373                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4374 00004CFC 6640                <1> 	inc	ax
  4375                              <1> 		; inc r1 / r1 = r1 + 1
  4376 00004CFE E87F060000          <1> 	call	imap
  4377                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4378                              <1> 			    ; /	inode map in r2 & m
  4379                              <1>   
  4380                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4381                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4382                              <1> 
  4383                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4384                              <1> 	;	       Inode count must be checked here
  4385                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4386                              <1> 
  4387                              <1> 	; 12/02/2022 - Retro UNIX 386 v1.0 (Kernel v0.2.0.18)
  4388                              <1> 	; (inode count check)
  4389                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4390                              <1> 
  4391 00004D03 730F                <1> 	jnc	short maknod2
  4392                              <1> 
  4393                              <1> 	; no free inode in inode table !
  4394 00004D05 C705[AB700000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4394 00004D0D 0000                <1>
  4395                              <1> 			; miscellaneous/other errors
  4396 00004D0F E9BFEDFFFF          <1> 	jmp	error	
  4397                              <1> maknod2: 	
  4398 00004D14 8413                <1> 	test	[ebx], dl
  4399                              <1> 		; bitb mq,(r2) / is the i-node active
  4400 00004D16 75E4                <1> 	jnz	short maknod1
  4401                              <1> 		; bne 1b / yes, try the next one
  4402 00004D18 0813                <1> 	or	[ebx], dl
  4403                              <1> 		; bisb mq,(r2) / no, make it active 
  4404                              <1> 			     ; / (put a 1 in the bit map)
  4405 00004D1A E8CA040000          <1> 	call	iget
  4406                              <1> 		; jsr r0,iget / get i-node into core
  4407                              <1> 	; 03/02/2022
  4408 00004D1F F605[596D0000]80    <1> 	test	byte [i.flgs+1], 80h
  4409                              <1> 	;test	word [i.flgs], 8000h 
  4410                              <1> 		; tst i.flgs / is i-node already allocated
  4411 00004D26 75D4                <1> 	jnz	short maknod1	
  4412                              <1> 		; blt 1b / yes, look for another one
  4413 00004D28 66A3[8E700000]      <1> 	mov	[u.dirbuf], ax
  4414                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4415                              <1> 	; 03/02/2022
  4416 00004D2E 58                  <1> 	pop	eax ; **
  4417                              <1> 	;pop	ax
  4418                              <1> 		; mov (sp)+,r1 / get current i-number back
  4419 00004D2F E8B5040000          <1> 	call	iget
  4420                              <1> 		; jsr r0,iget / get i-node in core
  4421 00004D34 E852F7FFFF          <1> 	call	mkdir
  4422                              <1> 		; jsr r0,mkdir / make a directory entry 
  4423                              <1> 			     ; / in current directory
  4424 00004D39 66A1[8E700000]      <1> 	mov	ax, [u.dirbuf]
  4425                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4426 00004D3F E8A5040000          <1> 	call	iget
  4427                              <1> 		; jsr r0,iget / get it into core
  4428                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4429                              <1> 	;mov	ecx, 8
  4430                              <1> 	; 03/02/2022 
  4431 00004D44 29C9                <1> 	sub	ecx, ecx
  4432 00004D46 B108                <1> 	mov	cl, 8
  4433 00004D48 31C0                <1> 	xor	eax, eax ; 0
  4434 00004D4A BF[586D0000]        <1> 	mov	edi, inode 
  4435 00004D4F F3AB                <1> 	rep	stosd
  4436                              <1> 	;
  4437 00004D51 668F05[586D0000]    <1> 	pop	word [i.flgs] ; *
  4438                              <1> 		; mov (sp)+,i.flgs / fill flags
  4439 00004D58 8A0D[A2700000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4440 00004D5E 880D[5B6D0000]      <1> 	mov 	[i.uid], cl
  4441                              <1> 		; movb u.uid,i.uid / user id	
  4442 00004D64 C605[5A6D0000]01    <1> 	mov     byte [i.nlks], 1
  4443                              <1> 		; movb $1,i.nlks / 1 link
  4444                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4445                              <1> 	;mov	eax, [s.time]
  4446                              <1> 	;mov 	[i.ctim], eax
  4447                              <1> 	 	; mov s.time,i.ctim / time created
  4448                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4449                              <1> 	; Retro UNIX 8086 v1 modification !
  4450                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4451                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4452                              <1> 	;call setimod
  4453                              <1> 		; jsr r0,setimod / set modified flag
  4454                              <1> 	;retn
  4455                              <1> 		; rts r0 / return
  4456                              <1> 	; 03/02/2022
  4457 00004D6B E983050000          <1> 	jmp	setimod
  4458                              <1> 
  4459                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4460                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4461                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4462                              <1> 	;
  4463                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4464                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4465                              <1> 	; The file descriptor refers to a file open for reading or
  4466                              <1> 	; writing. The read (or write) pointer is set as follows:
  4467                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4468                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4469                              <1> 	;	  current location plus offset.
  4470                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4471                              <1> 	;	  size of file plus offset.
  4472                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4473                              <1> 	;
  4474                              <1> 	; Calling sequence:
  4475                              <1> 	;	sysseek; offset; ptrname
  4476                              <1> 	; Arguments:
  4477                              <1> 	;	offset - number of bytes desired to move 
  4478                              <1> 	;		 the r/w pointer
  4479                              <1> 	;	ptrname - a switch indicated above
  4480                              <1> 	;
  4481                              <1> 	; Inputs: r0 - file descriptor 
  4482                              <1> 	; Outputs: -
  4483                              <1> 	; ...............................................................
  4484                              <1> 	;	
  4485                              <1> 	; Retro UNIX 8086 v1 modification: 
  4486                              <1> 	;       'sysseek' system call has three arguments; so,
  4487                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4488                              <1> 	;	* 2nd argument, offset is in CX register
  4489                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4490                              <1> 	;	
  4491                              <1> 
  4492 00004D70 E822000000          <1> 	call	seektell
  4493                              <1> 	; AX = u.count
  4494                              <1> 	; BX = *u.fofp
  4495                              <1> 		; jsr r0,seektell / get proper value in u.count
  4496                              <1> 		; add u.base,u.count / add u.base to it
  4497 00004D75 0305[7C700000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4498 00004D7B 8903                <1> 	mov	[ebx], eax
  4499                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4500 00004D7D E971EDFFFF          <1> 	jmp	sysret
  4501                              <1> 		; br sysret4
  4502                              <1> 
  4503                              <1> systell: ; / get the r/w pointer
  4504                              <1> 	; 03/02/2022
  4505                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4506                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4507                              <1> 	;
  4508                              <1> 	; Retro UNIX 8086 v1 modification:
  4509                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4510                              <1> 	; 	    it returns with error !
  4511                              <1> 	; Inputs: r0 - file descriptor 
  4512                              <1> 	; Outputs: r0 - file r/w pointer
  4513                              <1> 
  4514                              <1> 	;xor	ecx, ecx ; 0
  4515                              <1> 	;mov	edx, 1 ; 05/08/2013
  4516                              <1> 	; 03/02/2022
  4517 00004D82 29D2                <1> 	sub	edx, edx
  4518 00004D84 FEC2                <1> 	inc	dl
  4519                              <1> 	; edx = 1
  4520                              <1> 	;call 	seektell
  4521 00004D86 E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4522                              <1> 	;mov	ebx, [u.fofp]
  4523 00004D8B 8B03                <1> 	mov	eax, [ebx]
  4524 00004D8D A3[5C700000]        <1> 	mov	[u.r0], eax
  4525 00004D92 E95CEDFFFF          <1> 	jmp	sysret
  4526                              <1> 
  4527                              <1> ; Original unix v1 'systell' system call:
  4528                              <1> 		; jsr r0,seektell
  4529                              <1> 		; br error4
  4530                              <1> 
  4531                              <1> seektell:
  4532                              <1> 	; 03/02/2022
  4533                              <1> 	; 03/01/2016
  4534                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4535                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4536                              <1> 	;
  4537                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4538                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4539                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4540                              <1> 	; getf. The i-node is brought into core and then u.count
  4541                              <1> 	; is checked to see it is a 0, 1, or 2.
  4542                              <1> 	; If it is 0 - u.count stays the same
  4543                              <1> 	;          1 - u.count = offset (u.fofp)
  4544                              <1> 	;	   2 - u.count = i.size (size of file)
  4545                              <1> 	; 	 		
  4546                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4547                              <1> 	;	Argument 1, file descriptor is in BX;
  4548                              <1> 	;	Argument 2, offset is in CX;
  4549                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4550                              <1> 	;
  4551                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4552                              <1> 	; call 	arg
  4553                              <1> 	;
  4554                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4555                              <1> 	;
  4556 00004D97 890D[7C700000]      <1> 	mov 	[u.base], ecx ; offset
  4557                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4558                              <1> seektell0:
  4559 00004D9D 8915[80700000]      <1> 	mov 	[u.count], edx
  4560                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4561                              <1> 	; mov	ax, bx
  4562                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4563                              <1> 			     ; / (index in u.fp list)
  4564                              <1> 	; call	getf
  4565                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4566                              <1> 	; BX = file descriptor (file number)
  4567 00004DA3 E8F9FBFFFF          <1> 	call	getf1
  4568                              <1> 	; 03/02/2022
  4569 00004DA8 09C0                <1> 	or	eax, eax
  4570                              <1> 	;or	ax, ax ; i-number of the file
  4571                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4572                              <1> 		             ; / put it on the stack
  4573                              <1> 	;jz	error
  4574                              <1> 		; beq error4 / if i-number is 0, not active so error
  4575 00004DAA 750F                <1> 	jnz	short seektell1
  4576 00004DAC C705[AB700000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4576 00004DB4 0000                <1>
  4577 00004DB6 E918EDFFFF          <1> 	jmp	error
  4578                              <1> seektell1:
  4579                              <1> 	;push	eax
  4580 00004DBB 80FC80              <1> 	cmp	ah, 80h
  4581 00004DBE 7203                <1> 	jb	short seektell2
  4582                              <1> 		; bgt .+4 / if its positive jump
  4583 00004DC0 66F7D8              <1> 	neg	ax
  4584                              <1> 		; neg r1 / if not make it positive
  4585                              <1> seektell2:
  4586 00004DC3 E821040000          <1> 	call	iget
  4587                              <1> 		; jsr r0,iget / get its i-node into core
  4588 00004DC8 8B1D[6C700000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4589 00004DCE 803D[80700000]01    <1> 	cmp	byte [u.count], 1
  4590                              <1> 		; cmp u.count,$1 / is ptr name =1
  4591 00004DD5 7705                <1> 	ja	short seektell3
  4592                              <1> 		; blt 2f / no its zero
  4593 00004DD7 740A                <1> 	je	short seektell_4
  4594                              <1> 		; beq 1f / yes its 1
  4595 00004DD9 31C0                <1> 	xor	eax, eax
  4596                              <1> 	;jmp	short seektell_5
  4597 00004DDB C3                  <1> 	retn
  4598                              <1> seektell3:
  4599                              <1> 	; 03/01/2016
  4600                              <1> 	;movzx  eax, word [i.size]
  4601 00004DDC 66A1[5C6D0000]      <1> 	mov	ax, [i.size]
  4602                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4603                              <1>                                    ; / in file in u.count
  4604                              <1> 	;jmp	short seektell_5
  4605                              <1> 		; br 2f
  4606 00004DE2 C3                  <1> 	retn
  4607                              <1> seektell_4: ; 1: / ptrname =1
  4608                              <1> 	;mov	ebx, [u.fofp]
  4609 00004DE3 8B03                <1> 	mov	eax, [ebx]
  4610                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4611                              <1> ;seektell_5: ; 2: / ptrname =0
  4612                              <1> 	;mov	[u.count], eax
  4613                              <1> 	;pop	eax 
  4614                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4615 00004DE5 C3                  <1> 	retn
  4616                              <1> 		; rts r0
  4617                              <1> 
  4618                              <1> sysintr: ; / set interrupt handling
  4619                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4620                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4621                              <1> 	;
  4622                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4623                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4624                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4625                              <1> 	; If one does the interrupt character in the tty buffer is
  4626                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4627                              <1> 	; 'sysret' is just called.	
  4628                              <1> 	;
  4629                              <1> 	; Calling sequence:
  4630                              <1> 	;	sysintr; arg
  4631                              <1> 	; Argument:
  4632                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4633                              <1> 	;	    - if 1, intterupts cause their normal result
  4634                              <1> 	;		 i.e force an exit.
  4635                              <1> 	;	    - if arg is a location within the program,
  4636                              <1> 	;		control is passed to that location when
  4637                              <1> 	;		an interrupt occurs.	
  4638                              <1> 	; Inputs: -
  4639                              <1> 	; Outputs: -
  4640                              <1> 	; ...............................................................
  4641                              <1> 	;	
  4642                              <1> 	; Retro UNIX 8086 v1 modification: 
  4643                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4644                              <1> 	;	then branches into sysquit.
  4645                              <1> 	;
  4646 00004DE6 66891D[9A700000]    <1> 	mov	[u.intr], bx
  4647                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4648                              <1> 		; br 1f / go into quit routine
  4649 00004DED E901EDFFFF          <1> 	jmp	sysret
  4650                              <1> 
  4651                              <1> sysquit:
  4652                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4653                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4654                              <1> 	;
  4655                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4656                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4657                              <1> 	; tty exists. If one does the interrupt character in the tty
  4658                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4659                              <1> 	; 'sysret' is just called.	
  4660                              <1> 	;
  4661                              <1> 	; Calling sequence:
  4662                              <1> 	;	sysquit; arg
  4663                              <1> 	; Argument:
  4664                              <1> 	;	arg - if 0, this call diables quit signals from the
  4665                              <1> 	;		typewriter (ASCII FS)
  4666                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4667                              <1> 	;		cease and a core image to be produced.
  4668                              <1> 	;		 i.e force an exit.
  4669                              <1> 	;	    - if arg is an addres in the program,
  4670                              <1> 	;		a quit causes control to sent to that
  4671                              <1> 	;		location.	
  4672                              <1> 	; Inputs: -
  4673                              <1> 	; Outputs: -
  4674                              <1> 	; ...............................................................
  4675                              <1> 	;	
  4676                              <1> 	; Retro UNIX 8086 v1 modification: 
  4677                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4678                              <1> 	;	then branches into 'sysret'.
  4679                              <1> 	;
  4680 00004DF2 66891D[9C700000]    <1> 	mov	[u.quit], bx
  4681 00004DF9 E9F5ECFFFF          <1> 	jmp	sysret
  4682                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4683                              <1> 	;1:
  4684                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4685                              <1> 			      ; / to r1
  4686                              <1> 		; beq sysret4 / return to user
  4687                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4688                              <1> 			   ; / in the tty buffer
  4689                              <1> 		; br sysret4 / return to user
  4690                              <1> 
  4691                              <1> syssetuid: ; / set process id
  4692                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4693                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4694                              <1> 	;
  4695                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4696                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4697                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4698                              <1> 	; Only the super user can make this call.	
  4699                              <1> 	;
  4700                              <1> 	; Calling sequence:
  4701                              <1> 	;	syssetuid
  4702                              <1> 	; Arguments: -
  4703                              <1> 	;
  4704                              <1> 	; Inputs: (u.r0) - contains the process id.
  4705                              <1> 	; Outputs: -
  4706                              <1> 	; ...............................................................
  4707                              <1> 	;	
  4708                              <1> 	; Retro UNIX 8086 v1 modification: 
  4709                              <1> 	;       BL contains the (new) user ID of the current process
  4710                              <1> 
  4711                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4712 00004DFE 3A1D[A3700000]      <1> 	cmp	bl, [u.ruid] 
  4713                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4714                              <1> 			       ; / id number
  4715 00004E04 741E                <1> 	je	short setuid1
  4716                              <1> 		; beq 1f / yes
  4717 00004E06 803D[A2700000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4718                              <1> 		; tstb u.uid / no, is current user the super user?
  4719                              <1> 	;ja	error
  4720                              <1> 		; bne error4 / no, error
  4721 00004E0D 760F                <1> 	jna	short setuid0
  4722 00004E0F C705[AB700000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4722 00004E17 0000                <1>
  4723                              <1> 				; 'permission denied !' error
  4724 00004E19 E9B5ECFFFF          <1> 	jmp	error
  4725                              <1> setuid0:
  4726 00004E1E 881D[A3700000]      <1> 	mov	[u.ruid], bl
  4727                              <1> setuid1: ; 1:
  4728 00004E24 881D[A2700000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4729                              <1> 		; movb r1,u.uid / put process id in u.uid
  4730                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4731 00004E2A E9C4ECFFFF          <1> 	jmp	sysret
  4732                              <1> 		; br sysret4 / system return
  4733                              <1> 
  4734                              <1> sysgetuid: ; < get user id >
  4735                              <1> 	; 03/02/2022
  4736                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4737                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4738                              <1> 	;
  4739                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4740                              <1> 	; The real user ID identifies the person who is logged in,
  4741                              <1> 	; in contradistinction to the effective user ID, which
  4742                              <1> 	; determines his access permission at each moment. It is thus
  4743                              <1> 	; useful to programs which operate using the 'set user ID'
  4744                              <1> 	; mode, to find out who invoked them.	
  4745                              <1> 	;
  4746                              <1> 	; Calling sequence:
  4747                              <1> 	;	syssetuid
  4748                              <1> 	; Arguments: -
  4749                              <1> 	;
  4750                              <1> 	; Inputs: -
  4751                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4752                              <1> 	; ...............................................................
  4753                              <1> 	;	
  4754                              <1> 	; Retro UNIX 8086 v1 modification: 
  4755                              <1> 	;       AL contains the real user ID at return.
  4756                              <1> 	;
  4757                              <1> 	;movzx 	eax, byte [u.ruid]
  4758                              <1> 	; 03/03/2022
  4759 00004E2F A0[A3700000]        <1> 	mov	al, [u.ruid]
  4760 00004E34 A3[5C700000]        <1> 	mov	[u.r0], eax
  4761                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4762 00004E39 E9B5ECFFFF          <1> 	jmp	sysret
  4763                              <1> 		; br sysret4 / systerm return, sysret
  4764                              <1> 
  4765                              <1> anyi: 
  4766                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4767                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4768                              <1> 	;
  4769                              <1> 	; 'anyi' is called if a file deleted while open.
  4770                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4771                              <1> 	;
  4772                              <1> 	; INPUTS ->
  4773                              <1> 	;    r1 - contains an i-number
  4774                              <1> 	;    fsp - start of table containing open files
  4775                              <1> 	;
  4776                              <1> 	; OUTPUTS ->
  4777                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4778                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4779                              <1> 	;    if file not found - bit in i-node map is cleared
  4780                              <1> 	;    			 (i-node is freed)
  4781                              <1> 	;               all blocks related to i-node are freed
  4782                              <1> 	;	        all flags in i-node are cleared
  4783                              <1> 	; ((AX = R1)) input
  4784                              <1> 	;
  4785                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4786                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4787                              <1> 	;
  4788                              <1> 		; / r1 contains an i-number
  4789 00004E3E BB[286E0000]        <1> 	mov	ebx, fsp
  4790                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4791                              <1> anyi_1: ; 1:
  4792 00004E43 663B03              <1> 	cmp	ax, [ebx]
  4793                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4794 00004E46 7433                <1> 	je	short anyi_3
  4795                              <1> 		; beq 1f / yes, 1f
  4796 00004E48 66F7D8              <1> 	neg	ax
  4797                              <1> 		; neg r1 / no complement r1
  4798 00004E4B 663B03              <1> 	cmp	ax, [ebx]
  4799                              <1> 		; cmp r1,(r2) / do they match now?
  4800 00004E4E 742B                <1> 	je	short anyi_3
  4801                              <1> 		; beq 1f / yes, transfer
  4802                              <1> 		; / i-numbers do not match
  4803 00004E50 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4804                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4805                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4806 00004E53 81FB[1C700000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4807                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4808                              <1> 				; / are we at last entry in the table
  4809 00004E59 72E8                <1> 	jb	short anyi_1
  4810                              <1> 		; blt 1b / no, check next entries i-number
  4811                              <1> 	;cmp	ax, 32768
  4812 00004E5B 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4813                              <1> 		; tst r1 / yes, no match
  4814                              <1> 		; bge .+4
  4815 00004E5E 7203                <1> 	jb	short anyi_2
  4816 00004E60 66F7D8              <1> 	neg	ax
  4817                              <1> 		; neg r1 / make i-number positive
  4818                              <1> anyi_2:	
  4819 00004E63 E81A050000          <1> 	call	imap
  4820                              <1> 		; jsr r0,imap / get address of allocation bit 
  4821                              <1> 			    ; / in the i-map in r2
  4822                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4823                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4824                              <1>  	; not	dx
  4825 00004E68 F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4826                              <1>         ;and	[ebx], dx
  4827 00004E6A 2013                <1> 	and 	[ebx], dl 
  4828                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4829 00004E6C E8A4040000          <1> 	call	itrunc
  4830                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4831 00004E71 66C705[586D0000]00- <1>  	mov 	word [i.flgs], 0
  4831 00004E79 00                  <1>
  4832                              <1> 		; clr i.flgs / clear all flags in the i-node
  4833 00004E7A C3                  <1> 	retn
  4834                              <1> 		;rts	r0 / return
  4835                              <1> anyi_3: ; 1: / i-numbers match
  4836 00004E7B FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4837                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4838                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4839 00004E7E C3                  <1> 	retn
  4840                              <1> 		; rts r0
  2050                                  %include 'u3.s'        ; 10/05/2015
  2051                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC
  2052                              <1> ; Last Modification: 03/02/2022
  2053                              <1> ; ----------------------------------------------------------------------------
  2054                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2055                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2056                              <1> ;
  2057                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2058                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2059                              <1> ; <Bell Laboratories (17/3/1972)>
  2060                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2061                              <1> ;
  2062                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2063                              <1> ;
  2064                              <1> ; ****************************************************************************
  2065                              <1> ; 15/09/2015
  2066                              <1> 
  2067                              <1> tswitch: ; Retro UNIX 386 v1
  2068                              <1> tswap:
  2069                              <1> 	; 01/09/2015
  2070                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2071                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2072                              <1> 	; time out swap, called when a user times out.
  2073                              <1> 	; the user is put on the low priority queue.
  2074                              <1> 	; This is done by making a link from the last user
  2075                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2076                              <1> 	; then he is swapped out.
  2077                              <1> 	;
  2078                              <1> 	; Retro UNIX 386 v1 modification ->
  2079                              <1> 	;       swap (software task switch) is performed by changing
  2080                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2081                              <1> 	;	as in Retro UNIX 8086 v1.
  2082                              <1> 	;
  2083                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2084                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2085                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2086                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2087                              <1> 	;	compatibles was using 1MB segmented memory 
  2088                              <1> 	;	in 8086/8088 times.
  2089                              <1> 	;
  2090                              <1> 	; INPUTS ->
  2091                              <1> 	;    u.uno - users process number
  2092                              <1> 	;    runq+4 - lowest priority queue
  2093                              <1> 	; OUTPUTS ->
  2094                              <1> 	;    r0 - users process number
  2095                              <1> 	;    r2 - lowest priority queue address
  2096                              <1> 	;
  2097                              <1> 	; ((AX = R0, BX = R2)) output
  2098                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2099                              <1> 	;
  2100 00004E7F A0[A5700000]        <1> 	mov 	al, [u.uno]
  2101                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2102                              <1> 		; mov  $runq+4,r2 
  2103                              <1> 			; / move lowest priority queue address to r2
  2104 00004E84 E8CD000000          <1>         call 	putlu
  2105                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2106                              <1> 		             ; / u.uno's user
  2107                              <1> 
  2108                              <1> switch: ; Retro UNIX 386 v1
  2109                              <1> swap:
  2110                              <1> 	; 03/02/2022
  2111                              <1> 	; 02/09/2015
  2112                              <1> 	; 01/09/2015
  2113                              <1> 	; 31/08/2015
  2114                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2115                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2116                              <1> 	; 'swap' is routine that controls the swapping of processes
  2117                              <1> 	; in and out of core.
  2118                              <1> 	;
  2119                              <1> 	; Retro UNIX 386 v1 modification ->
  2120                              <1> 	;       swap (software task switch) is performed by changing
  2121                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2122                              <1> 	;	as in Retro UNIX 8086 v1.
  2123                              <1> 	;
  2124                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2125                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2126                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2127                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2128                              <1> 	;	compatibles was using 1MB segmented memory 
  2129                              <1> 	;	in 8086/8088 times.
  2130                              <1> 	;
  2131                              <1> 	; INPUTS ->
  2132                              <1> 	;    runq table - contains processes to run.
  2133                              <1> 	;    p.link - contains next process in line to be run.
  2134                              <1> 	;    u.uno - process number of process in core	
  2135                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2136                              <1> 	; OUTPUTS ->
  2137                              <1> 	;    (original unix v1 -> present process to its disk block)
  2138                              <1> 	;    (original unix v1 -> new process into core -> 
  2139                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2140                              <1> 	;	   for new process)
  2141                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2142                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2143                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2144                              <1> 	;	 for now, it will swap the process if there is not
  2145                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2146                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2147                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2148                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2149                              <1> 	;
  2150                              <1> 	;    u.pri -points to highest priority run Q.
  2151                              <1> 	;    r2 - points to the run queue.
  2152                              <1> 	;    r1 - contains new process number
  2153                              <1> 	;    r0 - points to place in routine or process that called
  2154                              <1> 	;	  swap all user parameters
  2155                              <1> 	;				
  2156                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2157                              <1> 	;
  2158                              <1> swap_0:
  2159                              <1> 		;mov $300,*$ps / processor priority = 6
  2160 00004E89 BE[4E700000]        <1> 	mov	esi, runq
  2161                              <1> 		; mov $runq,r2 / r2 points to runq table
  2162                              <1> swap_1: ; 1: / search runq table for highest priority process
  2163 00004E8E 668B06              <1> 	mov	ax, [esi]
  2164 00004E91 6621C0              <1> 	and 	ax, ax
  2165                              <1>        		; tst (r2)+ / are there any processes to run 
  2166                              <1> 			  ; / in this Q entry
  2167 00004E94 7507                <1> 	jnz	short swap_2
  2168                              <1>        		; bne 1f / yes, process 1f
  2169                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2170                              <1> 			       ; / to end of table
  2171                              <1> 		; bne 1b / if not at end, go back
  2172 00004E96 E8E0000000          <1> 	call	idle
  2173                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2174                              <1> 				       ; / all queues are empty
  2175 00004E9B EBF1                <1> 	jmp	short swap_1
  2176                              <1> 		; br swap
  2177                              <1> swap_2: ; 1:
  2178 00004E9D 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2179                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2180                              <1>  		; mov r2,u.pri / set present user to this run queue
  2181                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2182 00004EA0 38E0                <1> 	cmp	al, ah
  2183                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2184                              <1> 			      ; / in this Q to be run
  2185 00004EA2 740A                <1> 	je	short swap_3
  2186                              <1>        		; beq 1f / yes
  2187                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2188                              <1> 	;movzx	ebx, al
  2189 00004EA4 8AA3[C76D0000]      <1> 	mov	ah, [ebx+p.link-1] 
  2190 00004EAA 8826                <1>        	mov	[esi], ah
  2191                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2192                              <1> 				       ; / in line into run queue
  2193 00004EAC EB05                <1> 	jmp	short swap_4
  2194                              <1>        		; br 2f
  2195                              <1> swap_3: ; 1:
  2196                              <1> 	;xor	dx, dx
  2197                              <1> 	; 03/02/2022
  2198 00004EAE 31D2                <1> 	xor	edx, edx
  2199 00004EB0 668916              <1> 	mov	[esi], dx
  2200                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2201                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2202                              <1>       ; / in new process if required
  2203                              <1>        		; clr *$ps / clear processor status
  2204 00004EB3 8A25[A5700000]      <1> 	mov 	ah, [u.uno]
  2205 00004EB9 38C4                <1> 	cmp	ah, al
  2206                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2207                              <1> 			      ; / the process in core?
  2208 00004EBB 743B                <1>        	je	short swap_8
  2209                              <1>        		; beq 2f / yes, don't have to swap
  2210                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2211                              <1> 			   ; / (address in routine that called swap)
  2212                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2213                              <1> 	; 01/09/2015
  2214                              <1> 	;mov	[u.usp], esp
  2215                              <1>        		; mov sp,u.usp / save stack pointer
  2216                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2217                              <1> 			       ; / to the stack pointer
  2218 00004EBD 08E4                <1> 	or	ah, ah
  2219                              <1>        		; tstb u.uno / is the process # = 0
  2220 00004EBF 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2221                              <1> 		; beq  1f / yes, kill process by overwriting
  2222                              <1> 	; 02/09/2015
  2223 00004EC1 8925[58700000]      <1> 	mov	[u.usp], esp ; return  address for 'syswait' & 'sleep'
  2224                              <1> 	;
  2225 00004EC7 E834000000          <1> 	call	wswap
  2226                              <1> 		;jsr r0,wswap / write out core to disk
  2227                              <1> 	 ; 31/08/2015
  2228                              <1> 	;movzx	ebx, al ; New (running) process number
  2229 00004ECC EB1C                <1> 	jmp 	short swap_7
  2230                              <1> swap_6:
  2231                              <1> 	; 31/08/2015
  2232                              <1> 	; Deallocate memory pages belong to the process
  2233                              <1> 	; which is being terminated
  2234                              <1> 	; 14/05/2015 ('sysexit')
  2235                              <1>  	; Deallocate memory pages of the process
  2236                              <1> 	; (Retro UNIX 386 v1 modification !)
  2237                              <1> 	;
  2238                              <1> 	; movzx ebx, al
  2239 00004ECE 53                  <1> 	push	ebx
  2240 00004ECF A1[AF700000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2241 00004ED4 8B1D[B3700000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2242 00004EDA E81DE0FFFF          <1> 	call	deallocate_page_dir
  2243 00004EDF A1[A6700000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2244 00004EE4 E8ABE0FFFF          <1> 	call	deallocate_page
  2245 00004EE9 5B                  <1> 	pop	ebx
  2246                              <1> swap_7: ;1: 
  2247                              <1> 	; 02/09/2015
  2248                              <1> 	; 31/08/2015
  2249                              <1> 	; 14/05/2015
  2250 00004EEA C0E302              <1> 	shl	bl, 2 ; * 4 
  2251 00004EED 8B83[E46D0000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2252                              <1> 	;cli
  2253 00004EF3 E831000000          <1> 	call	rswap
  2254                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2255                              <1> 		; jsr r0,rswap / read new process into core
  2256                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2257                              <1> 			      ; / to his program to its normal
  2258                              <1> 	; 01/09/2015
  2259                              <1> 	;mov	esp, [u.usp]	
  2260                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2261                              <1> 			     ; / new process stack
  2262                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2263                              <1> 			     ; / that just got swapped in, left off.,
  2264                              <1> 			     ; / i.e., transfer control to new process
  2265                              <1> 	;sti
  2266                              <1> swap_8: ;2:
  2267                              <1> 	; RETRO UNIX 8086 v1 modification !
  2268 00004EF8 C605[98700000]04    <1> 	mov	byte [u.quant], time_count 
  2269                              <1> 		; movb $30.,uquant / initialize process time quantum
  2270 00004EFF C3                  <1> 	retn
  2271                              <1> 		; rts r0 / return
  2272                              <1> 
  2273                              <1> wswap:  ; < swap out, swap to disk >
  2274                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2275                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2276                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2277                              <1> 	; appropriate disk area.
  2278                              <1> 	;
  2279                              <1> 	; Retro UNIX 386 v1 modification ->
  2280                              <1> 	;       User (u) structure content and the user's register content
  2281                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2282                              <1> 	;	saving 'u' structure and user registers for task switching).
  2283                              <1> 	;	u.usp - points to kernel stack address which contains
  2284                              <1> 	;		user's registers while entering system call.  
  2285                              <1> 	;	u.sp  - points to kernel stack address 
  2286                              <1> 	;		to return from system call -for IRET-.
  2287                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2288                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2289                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2290                              <1> 	;
  2291                              <1> 	; Retro UNIX 8086 v1 modification ->
  2292                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2293                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2294                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2295                              <1> 	;	compatibles was using 1MB segmented memory 
  2296                              <1> 	;	in 8086/8088 times.
  2297                              <1> 	;
  2298                              <1> 	; INPUTS ->
  2299                              <1> 	;    u.break - points to end of program
  2300                              <1> 	;    u.usp - stack pointer at the moment of swap
  2301                              <1> 	;    core - beginning of process program		
  2302                              <1> 	;    ecore - end of core 	
  2303                              <1> 	;    user - start of user parameter area		
  2304                              <1> 	;    u.uno - user process number	
  2305                              <1> 	;    p.dska - holds block number of process	
  2306                              <1> 	; OUTPUTS ->
  2307                              <1> 	;    swp I/O queue
  2308                              <1> 	;    p.break - negative word count of process 
  2309                              <1> 	;    r1 - process disk address	
  2310                              <1> 	;    r2 - negative word count
  2311                              <1> 	;
  2312                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2313                              <1> 	;
  2314                              <1> 	; INPUTS ->
  2315                              <1> 	;    u.uno - process number (to be swapped out)
  2316                              <1> 	; OUTPUTS ->
  2317                              <1> 	;    none
  2318                              <1> 	;
  2319                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2320                              <1> 	;
  2321 00004F00 8B3D[A6700000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2322 00004F06 B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2323 00004F0B BE[54700000]        <1> 	mov	esi, user ; active user (u) structure	
  2324 00004F10 F3A5                <1> 	rep	movsd
  2325                              <1> 	;
  2326 00004F12 8B35[58700000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2327                              <1> 			     ;      points to user registers)
  2328 00004F18 8B0D[54700000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2329                              <1> 			     ; (for IRET)
  2330                              <1> 			     ; [u.sp] -> EIP (user)
  2331                              <1> 			     ; [u.sp+4]-> CS (user)
  2332                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2333                              <1> 			     ; [u.sp+12] -> ESP (user)
  2334                              <1> 			     ; [u.sp+16] -> SS (user)	
  2335 00004F1E 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2336 00004F20 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2337                              <1> 			     ; (for IRET) 	
  2338 00004F23 C1E902              <1> 	shr	ecx, 2	     		
  2339 00004F26 F3A5                <1> 	rep	movsd
  2340 00004F28 C3                  <1> 	retn
  2341                              <1> 
  2342                              <1> 	; Original UNIX v1 'wswap' routine:
  2343                              <1> 	; wswap:
  2344                              <1> 		; mov *$30,u.emt / determines handling of emts
  2345                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2346                              <1> 				; / illegal instructions
  2347                              <1> 		; mov u.break,r2 / put process program break address in r2
  2348                              <1> 		; inc r2 / add 1 to it 
  2349                              <1> 		; bic $1,r2 / make it even
  2350                              <1> 		; mov r2,u.break / set break to an even location
  2351                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2352                              <1> 			     ; / at moment of swap in r3
  2353                              <1> 		; cmp r2,$core / is u.break less than $core
  2354                              <1> 		; blos 2f / yes
  2355                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2356                              <1>        		; bhis 2f / yes
  2357                              <1> 	; 1:
  2358                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2359                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2360                              <1> 		; bne 1b / no, keep packing
  2361                              <1> 	 	; br 1f / yes
  2362                              <1> 	; 2:
  2363                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2364                              <1> 	; 1:
  2365                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2366                              <1> 			   ; / (user up to end of stack gets written out)
  2367                              <1> 		; neg r2 / make it negative
  2368                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2369                              <1> 		; mov r2,swp+4 / word count
  2370                              <1> 		; movb u.uno,r1 / move user process number to r1
  2371                              <1> 		; asl r1 / x2 for index
  2372                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2373                              <1> 				     ; / into the p.break table
  2374                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2375                              <1> 				    ; /	for process to r1
  2376                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2377                              <1> 			     ; / (block number)
  2378                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2379                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2380                              <1> 	; 1:
  2381                              <1>        		; tstb swp+1 / is lt done writing?
  2382                              <1>        		; bne 1b / no, wait
  2383                              <1> 		; rts r0 / yes, return to swap
  2384                              <1> 
  2385                              <1> rswap:  ; < swap in, swap from disk >
  2386                              <1> 	; 15/09/2015
  2387                              <1> 	; 28/08/2015
  2388                              <1> 	; 14/05/2015
  2389                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2390                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2391                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2392                              <1> 	; from disk into core.
  2393                              <1> 	;
  2394                              <1> 	; Retro UNIX 386 v1 modification ->
  2395                              <1> 	;       User (u) structure content and the user's register content
  2396                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2397                              <1> 	;	saving 'u' structure and user registers for task switching).
  2398                              <1> 	;	u.usp - points to kernel stack address which contains
  2399                              <1> 	;		user's registers while entering system call.  
  2400                              <1> 	;	u.sp  - points to kernel stack address 
  2401                              <1> 	;		to return from system call -for IRET-.
  2402                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2403                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2404                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2405                              <1> 	;
  2406                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2407                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2408                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2409                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2410                              <1> 	;	compatibles was using 1MB segmented memory 
  2411                              <1> 	;	in 8086/8088 times.
  2412                              <1> 	;
  2413                              <1> 	; INPUTS ->
  2414                              <1> 	;    r1 - process number of process to be read in
  2415                              <1> 	;    p.break - negative of word count of process 
  2416                              <1> 	;    p.dska - disk address of the process		
  2417                              <1> 	;    u.emt - determines handling of emt's 	
  2418                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2419                              <1> 	; OUTPUTS ->
  2420                              <1> 	;    8 = (u.ilgins)
  2421                              <1> 	;    24 = (u.emt)
  2422                              <1> 	;    swp - bit 10 is set to indicate read 
  2423                              <1> 	;		(bit 15=0 when reading is done)	
  2424                              <1> 	;    swp+2 - disk block address
  2425                              <1> 	;    swp+4 - negative word count 	
  2426                              <1> 	;      ((swp+6 - address of user structure)) 
  2427                              <1> 	;
  2428                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2429                              <1> 	;
  2430                              <1> 	; INPUTS ->
  2431                              <1> 	;    AL	- new process number (to be swapped in)	 
  2432                              <1> 	; OUTPUTS ->
  2433                              <1> 	;    none
  2434                              <1> 	;
  2435                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2436                              <1> 	;
  2437                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2438 00004F29 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2439 00004F2B B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2440 00004F30 BF[54700000]        <1> 	mov	edi, user ; active user (u) structure	
  2441 00004F35 F3A5                <1> 	rep	movsd
  2442 00004F37 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2443 00004F38 8B3D[58700000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2444                              <1> 			     ;      points to user registers)
  2445 00004F3E 8B0D[54700000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2446                              <1> 			     ; (for IRET)
  2447                              <1> 			     ; [u.sp] -> EIP (user)
  2448                              <1> 			     ; [u.sp+4]-> CS (user)
  2449                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2450                              <1> 			     ; [u.sp+12] -> ESP (user)
  2451                              <1> 			     ; [u.sp+16] -> SS (user)		
  2452                              <1> 	; 28/08/2015
  2453 00004F44 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2454 00004F46 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2455                              <1> 			     ; (for IRET) 	
  2456 00004F49 C1E902              <1> 	shr	ecx, 2	       		
  2457 00004F4C F3A5                <1> 	rep	movsd
  2458 00004F4E 8B25[58700000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2459 00004F54 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2460 00004F55 C3                  <1> 	retn
  2461                              <1> 
  2462                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2463                              <1> 	;rswap:
  2464                              <1>        		; asl r1 / process number x2 for index
  2465                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2466                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2467                              <1>        		; bis $2000,swp / read
  2468                              <1>        		; jsr r0,ppoke / read it in 
  2469                              <1> 	; 1:
  2470                              <1>        		; tstb swp+1 / done
  2471                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2472                              <1>        		; mov u.emt,*$30 / yes move these
  2473                              <1>        		; mov u.ilgins,*$10 / back
  2474                              <1>        		; rts r0 / return
  2475                              <1> 
  2476                              <1> 	;unpack: ; / move stack back to its normal place
  2477                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2478                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2479                              <1> 		; blos 2f / yes, return
  2480                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2481                              <1> 			     ; / before swapping
  2482                              <1> 		; bhis 2f / yes, return
  2483                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2484                              <1> 		; add r3,r2
  2485                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2486                              <1> 	; 1:
  2487                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2488                              <1> 		; cmp r2,u.break / in core
  2489                              <1> 		; bne 1b
  2490                              <1> 	; 2:
  2491                              <1>        		; rts r0
  2492                              <1> 
  2493                              <1> putlu: 
  2494                              <1> 	; 12/09/2015
  2495                              <1> 	; 02/09/2015
  2496                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2497                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2498                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2499                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2500                              <1> 	; the last process on the queue to process in r1 by putting
  2501                              <1> 	; the process number in r1 into the last process's link.
  2502                              <1> 	;
  2503                              <1> 	; INPUTS ->
  2504                              <1> 	;    r1 - user process number
  2505                              <1> 	;    r2 - points to lowest priority queue 
  2506                              <1> 	;    p.dska - disk address of the process		
  2507                              <1> 	;    u.emt - determines handling of emt's 	
  2508                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2509                              <1> 	; OUTPUTS ->
  2510                              <1> 	;    r3 - process number of last process on the queue upon
  2511                              <1> 	;	  entering putlu
  2512                              <1> 	;    p.link-1 + r3 - process number in r1
  2513                              <1> 	;    r2 - points to lowest priority queue
  2514                              <1> 	;
  2515                              <1> 	; ((Modified registers: EDX, EBX)) 
  2516                              <1> 	;
  2517                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2518                              <1> 
  2519                              <1> 	; eBX = r2
  2520                              <1> 	; eAX = r1 (AL=r1b)
  2521                              <1> 
  2522 00004F56 BB[4E700000]        <1> 	mov	ebx, runq
  2523 00004F5B 0FB613              <1> 	movzx  	edx, byte [ebx]
  2524 00004F5E 43                  <1> 	inc	ebx
  2525 00004F5F 20D2                <1> 	and	dl, dl
  2526                              <1> 		; tstb (r2)+ / is queue empty?
  2527 00004F61 740A                <1>        	jz	short putlu_1
  2528                              <1> 		; beq 1f / yes, branch
  2529 00004F63 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2530                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2531                              <1> 			     ; / in r3
  2532 00004F65 8882[C76D0000]      <1>        	mov	[edx+p.link-1], al
  2533                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2534                              <1> 			     ; / "last users" link
  2535 00004F6B EB03                <1> 	jmp	short putlu_2
  2536                              <1> 		; br 2f /
  2537                              <1> putlu_1: ; 1:
  2538 00004F6D 8843FF              <1> 	mov	[ebx-1], al
  2539                              <1>        		; movb r1,-1(r2) / user is only user; 
  2540                              <1> 			    ; / put process no. at beginning and at end
  2541                              <1> putlu_2: ; 2: 
  2542 00004F70 8803                <1> 	mov	[ebx], al
  2543                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2544                              <1> 			     ; / on the queue
  2545 00004F72 88C2                <1> 	mov	dl, al
  2546 00004F74 88B2[C76D0000]      <1>         mov     [edx+p.link-1], dh ; 0
  2547                              <1> 		; dec r2 / restore r2
  2548 00004F7A C3                  <1>         retn
  2549                              <1> 		; rts r0
  2550                              <1> 
  2551                              <1> ;copyz:
  2552                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2553                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2554                              <1> ;       mov     (r0)+,r1
  2555                              <1> ;       mov     (r0)+,r2
  2556                              <1> ;1:
  2557                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2558                              <1> ;       cmp     r1,r2 
  2559                              <1> ;       blo     1b
  2560                              <1> ;       mov     (sp)+,r2 / restore r2
  2561                              <1> ;       mov     (sp)+,r1 / restore r1
  2562                              <1> ;       rts     r0 
  2563                              <1> 
  2564                              <1> idle:
  2565                              <1> 	; 01/09/2015
  2566                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2567                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2568                              <1> 	; (idle & wait loop)
  2569                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2570                              <1> 	; idle procedure!
  2571                              <1>       	;
  2572                              <1>   	; 01/09/2015
  2573 00004F7B FB                  <1> 	sti
  2574                              <1>       	; 29/07/2013
  2575 00004F7C F4                  <1>       	hlt
  2576 00004F7D 90                  <1>       	nop ; 10/10/2013
  2577 00004F7E 90                  <1>       	nop
  2578 00004F7F 90                  <1>       	nop
  2579                              <1>       	; 23/10/2013
  2580 00004F80 90                  <1>       	nop
  2581 00004F81 90                  <1>       	nop
  2582 00004F82 90                  <1>       	nop
  2583 00004F83 90                  <1>       	nop
  2584 00004F84 C3                  <1>       	retn      
  2585                              <1> 
  2586                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2587                              <1> 	;clr *$ps / clear ps
  2588                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2589                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2590                              <1> 	;1 / wait for interrupt
  2591                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2592                              <1> 	;mov (sp)+,*$ps
  2593                              <1> 	;rts r0
  2594                              <1> 
  2595                              <1> clear:
  2596                              <1> 	; 03/02/2022
  2597                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2598                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2599                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2600                              <1> 	; on the current device (cdev)
  2601                              <1> 	;	
  2602                              <1> 	; INPUTS ->
  2603                              <1> 	;    r1 - block number of block to be zeroed
  2604                              <1> 	;    cdev - current device number 
  2605                              <1> 	; OUTPUTS ->
  2606                              <1> 	;    a zeroed I/O buffer onto the current device
  2607                              <1> 	;    r1 - points to last entry in the I/O buffer
  2608                              <1> 	;
  2609                              <1> 	; ((AX = R1)) input/output
  2610                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2611                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2612                              <1> 
  2613 00004F85 E8A20E0000          <1> 	call 	wslot
  2614                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2615                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2616 00004F8A 89DF                <1> 	mov	edi, ebx ; r5
  2617 00004F8C 89C2                <1> 	mov	edx, eax
  2618 00004F8E B980000000          <1> 	mov	ecx, 128
  2619                              <1> 		; mov $256.,r3
  2620 00004F93 31C0                <1> 	xor	eax, eax
  2621 00004F95 F3AB                <1> 	rep	stosd
  2622 00004F97 89D0                <1> 	mov	eax, edx
  2623                              <1> ; 1: 
  2624                              <1>        		; clr (r5)+ / zero data word in buffer
  2625                              <1>        		; dec r3
  2626                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2627                              <1> 	;call	dskwr
  2628                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2629                              <1>                              ; / block specified in r1
  2630                              <1> 	; eAX (r1) = block number
  2631                              <1> 	;retn
  2632                              <1> 		; rts r0
  2633                              <1> 	; 03/02/2022
  2634 00004F99 E9AA0E0000          <1> 	jmp	dskwr
  2051                                  %include 'u4.s'        ; 15/04/2015
  2052                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC
  2053                              <1> ; Last Modification: 26/02/2022
  2054                              <1> ; ----------------------------------------------------------------------------
  2055                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2056                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2057                              <1> ;
  2058                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2059                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2060                              <1> ; <Bell Laboratories (17/3/1972)>
  2061                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2062                              <1> ;
  2063                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2064                              <1> ;
  2065                              <1> ; ****************************************************************************
  2066                              <1> ; 14/10/2015
  2067                              <1> 
  2068                              <1> ;setisp:
  2069                              <1>        ;mov     r1,-(sp)
  2070                              <1>        ;mov     r2,-(sp)
  2071                              <1>        ;mov     r3,-(sp)
  2072                              <1>        ;mov     clockp,-(sp)
  2073                              <1>        ;mov     $s.syst+2,clockp
  2074                              <1>        ;jmp     (r0)
  2075                              <1> 
  2076                              <1> clock: ; / interrupt from 60 cycle clock
  2077                              <1> 	
  2078                              <1> 	; 14/10/2015
  2079                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2080                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2081                              <1> 
  2082                              <1>        ;mov     r0,-(sp) / save r0
  2083                              <1>        ;tst     *$lks / restart clock?
  2084                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2085                              <1>        ;inc     (r0)
  2086                              <1>        ;bne     1f
  2087                              <1>        ;inc     -(r0)
  2088                              <1> ;1:
  2089                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2090                              <1>        ;inc     (r0)
  2091                              <1>        ;bne     1f
  2092                              <1>        ;inc     -(r0)
  2093                              <1> ;1:
  2094                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2095                              <1> 
  2096 00004F9E 803D[98700000]00    <1> 	cmp	byte [u.quant], 0
  2097 00004FA5 772C                <1> 	ja	short clk_1
  2098                              <1> 	;
  2099 00004FA7 803D[53700000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2100 00004FAE 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2101 00004FB0 803D[A5700000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2102 00004FB7 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2103 00004FB9 66833D[9A700000]00  <1> 	cmp	word [u.intr], 0
  2104 00004FC1 7616                <1> 	jna	short clk_2
  2105                              <1> clk_0:
  2106                              <1> 	; 14/10/2015
  2107 00004FC3 FE05[53700000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2108 00004FC9 58                  <1> 	pop	eax ; return address to the timer interrupt
  2109                              <1> 	;
  2110 00004FCA B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2111                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2112 00004FCC E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2113                              <1> 	;
  2114 00004FCE E97CEBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2115                              <1> clk_1:
  2116 00004FD3 FE0D[98700000]      <1> 	dec	byte [u.quant]
  2117                              <1> clk_2:
  2118 00004FD9 C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2119                              <1> 
  2120                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2121                              <1> 
  2122                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2123                              <1>        ;decb    (r0)
  2124                              <1>        ;bge     1f / if less than 0
  2125                              <1>        ;clrb    (r0) / make it 0
  2126                              <1> ;1: / decrement time out counts return now if priority was not 0
  2127                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2128                              <1>        ;bge     2f / yes, check time outs
  2129                              <1>        ;tstb    (r0) / no, user timed out?
  2130                              <1>        ;bne     1f / no
  2131                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2132                              <1>        ;bne     1f / no, 1f
  2133                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2134                              <1>        ;sys     0 / sysrele
  2135                              <1>        ;rti
  2136                              <1> ;2: / priority is high so just decrement time out counts
  2137                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2138                              <1> ;2:
  2139                              <1>        ;tstb    (r0) / is the time out?
  2140                              <1>        ;beq     3f / yes, 3f (get next entry)
  2141                              <1>        ;decb    (r0) / no, decrement the time
  2142                              <1>        ;bne     3f / isit zero now?
  2143                              <1>        ;incb    (r0) / yes, increment the time
  2144                              <1> ;3:
  2145                              <1>        ;inc     r0 / next entry
  2146                              <1>        ;cmp     r0,$touts / end of toutt table?
  2147                              <1>        ;blo     2b / no, check this entry
  2148                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2149                              <1>        ;rti / return from interrupt
  2150                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2151                              <1>        ;mov     (sp)+,r0 / restore r0
  2152                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2153                              <1>        ;jsr     r0,setisp / save registers
  2154                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2155                              <1>                                ;  / the table
  2156                              <1> ;1:
  2157                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2158                              <1>        ;beq     2f / yes
  2159                              <1>        ;decb    toutt(r0) / no, decrement the time
  2160                              <1>        ;bne     2f / is the time 0, now
  2161                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2162                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2163                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2164                              <1> ;2:
  2165                              <1>        ;dec     r0 / set up r0 for next entry
  2166                              <1>        ;bge     1b / finished? , no, go back
  2167                              <1>        ;br      retisp / yes, restore registers and do a rti
  2168                              <1> 
  2169                              <1> ;retisp:
  2170                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2171                              <1>        ;mov     (sp)+,r3
  2172                              <1>        ;mov     (sp)+,r2
  2173                              <1>        ;mov     (sp)+,r1
  2174                              <1>        ;mov     (sp)+,r0
  2175                              <1>        ;rti     / return from interrupt
  2176                              <1> 
  2177                              <1> 
  2178                              <1> wakeup: ; / wakeup processes waiting for an event 
  2179                              <1> 	; / by linking them to the queue
  2180                              <1> 	;
  2181                              <1> 	; 26/02/2022
  2182                              <1> 	; 15/09/2015
  2183                              <1> 	; 29/06/2015
  2184                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2185                              <1> 	;
  2186                              <1> 	; 15/05/2013 - 02/06/2014
  2187                              <1> 	; Retro UNIX 8086 v1 modification !
  2188                              <1> 	; (Process/task switching routine by using
  2189                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2190                              <1> 	;
  2191                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2192                              <1> 	; sleeping in the specified wait channel by creating a link 
  2193                              <1> 	; to it from the last user process on the run queue.
  2194                              <1> 	; If there is no process to wake up, nothing happens.
  2195                              <1> 	;
  2196                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2197                              <1> 	; 'switching' status of the current process (owns current tty)
  2198                              <1> 	; (via alt + function keys) to a process which has highest
  2199                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2200                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2201                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2202                              <1> 	; tty for tty switching by keyboard.)	 
  2203                              <1> 	; 
  2204                              <1> 	; INPUT -> 
  2205                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2206                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2207                              <1> 	;
  2208                              <1> 	; ((modified registers: EAX, EBX))
  2209                              <1> 	;
  2210 00004FDA 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2211 00004FDD 81C3[F86C0000]      <1> 	add	ebx, wlist
  2212 00004FE3 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2213 00004FE5 20C0                <1> 	and	al, al
  2214 00004FE7 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2215                              <1> 	;
  2216 00004FE9 30E4                <1> 	xor	ah, ah
  2217 00004FEB 8825[98700000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2218 00004FF1 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2219                              <1> 	; 15/09/2015
  2220 00004FF3 0FB6D8              <1> 	movzx	ebx, al
  2221                              <1> 	; 26/02/2022 (p.waitc is not used)
  2222                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2223 00004FF6 FEC4                <1> 	inc	ah
  2224 00004FF8 88A3[D76D0000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2225                              <1> 	;
  2226 00004FFE 57                  <1> 	push	edi
  2227 00004FFF 52                  <1> 	push	edx
  2228 00005000 E851FFFFFF          <1> 	call	putlu
  2229 00005005 5A                  <1> 	pop	edx
  2230 00005006 5F                  <1> 	pop	edi
  2231                              <1> wa0:
  2232 00005007 C3                  <1> 	retn
  2233                              <1> 
  2234                              <1> sleep: 
  2235                              <1> 	; 26/02/2022
  2236                              <1> 	; 03/02/2022
  2237                              <1> 	; 15/09/2015
  2238                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2239                              <1> 	;
  2240                              <1> 	; 09/05/2013 - 20/03/2014
  2241                              <1> 	;
  2242                              <1> 	; Retro UNIX 8086 v1 modification !
  2243                              <1> 	; (Process/task switching and quit routine by using
  2244                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2245                              <1> 	;
  2246                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2247                              <1> 	; tty and tape output or input becomes available
  2248                              <1> 	; and process is put on waiting channel and swapped out,
  2249                              <1> 	; then -when the tty or tape is ready to write or read-
  2250                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2251                              <1> 	;
  2252                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2253                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2254                              <1> 	; status of the current process also INT 1Ch will count down
  2255                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2256                              <1> 	; to tty buffer of the current process and kernel will get
  2257                              <1> 	; user input by using tty buffer of the current process
  2258                              <1> 	; (instead of standard INT 16h interrupt).
  2259                              <1> 	; TTY output will be redirected to related video page of text mode
  2260                              <1> 	; (INT 10h will be called with different video page depending
  2261                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2262                              <1> 	; pseudo screens.)
  2263                              <1> 	;
  2264                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2265                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2266                              <1> 	; characters/data on serial port(s).
  2267                              <1> 	;
  2268                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2269                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2270                              <1> 	; 
  2271                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2272                              <1> 	;
  2273                              <1> 	;; 05/10/2013
  2274                              <1>         ;10/12/2013
  2275                              <1> 	;cmp   byte [u.uno], 1
  2276                              <1>         ;ja    short sleep0
  2277                              <1> 	;retn
  2278                              <1> 
  2279                              <1> 	; 20/03/2014
  2280                              <1> 	;mov	bx, [runq]
  2281                              <1> 	;cmp	bl, bh
  2282                              <1> 	;jne	short sleep0	
  2283                              <1> 	; 25/02/2014
  2284                              <1> 	;cmp word ptr [runq], 0
  2285                              <1> 	;ja short sleep0	
  2286                              <1> 	;retn
  2287                              <1> sleep0:
  2288                              <1> 	;
  2289 00005008 E849000000          <1> 	call	isintr
  2290                              <1> 	;jnz	sysret
  2291                              <1> 		; / wait for event
  2292                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2293                              <1> 			      ; / or quit from user
  2294                              <1>                		; br 2f / something happened
  2295                              <1> 			      ; / yes, his interrupt so return
  2296                              <1>                      	      ;	/ to user
  2297                              <1> 	; 03/02/2022
  2298 0000500D 7405                <1> 	jz	short sleep_2
  2299                              <1> sleep_3:
  2300 0000500F E9DFEAFFFF          <1> 	jmp	sysret
  2301                              <1> sleep_2:
  2302                              <1> 	; 30/06/2015
  2303 00005014 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2304 00005017 81C3[F86C0000]      <1> 	add	ebx, wlist
  2305 0000501D 8A03                <1> 	mov	al, [ebx]
  2306 0000501F 20C0                <1> 	and	al, al
  2307 00005021 7407                <1> 	jz	short sleep1
  2308 00005023 53                  <1> 	push	ebx
  2309 00005024 E82DFFFFFF          <1> 	call	putlu
  2310 00005029 5B                  <1> 	pop	ebx
  2311                              <1> sleep1:
  2312 0000502A A0[A5700000]        <1> 	mov	al, [u.uno]    
  2313 0000502F 8803                <1>   	mov	[ebx], al 	; put the process number
  2314                              <1> 				; in the wait channel
  2315                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2316                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2317                              <1> 				     ; / on the stack
  2318                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2319                              <1> 				     ; / to put to sleep in there
  2320                              <1>         ; 15/09/2015
  2321 00005031 0FB6D8              <1> 	movzx	ebx, al
  2322 00005034 C683[D76D0000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2323                              <1> 	; 26/02/2022 (p.waitc is not used)
  2324                              <1> 	;inc	ah
  2325                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2326                              <1> 	;
  2327 0000503B 66FF35[40700000]    <1> 	push    word [cdev]
  2328                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2329 00005042 E842FEFFFF          <1> 	call	swap
  2330                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2331 00005047 668F05[40700000]    <1>         pop     word [cdev]
  2332                              <1> 		; mov (sp)+,cdev / restore device
  2333 0000504E E803000000          <1> 	call	isintr
  2334                              <1> 	; 22/09/2013
  2335                              <1> 	;jnz	sysret         
  2336                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2337                              <1>                		; br 2f / yes, return to new user
  2338                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2339                              <1> 				; / originally on the wait channel
  2340                              <1>        		; beq 1f / if 0 branch
  2341                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2342                              <1>        		; mov $300,*$ps / processor priority = 6
  2343                              <1> 		; jsr r0,putlu / create link to old process number
  2344                              <1>        		; clr *$ps / clear the status; process priority = 0
  2345                              <1> 	; 03/02/2022
  2346 00005053 75BA                <1> 	jnz	short sleep_3
  2347                              <1>      ;1:
  2348 00005055 C3                  <1> 	retn
  2349                              <1> 		; rts r0 / return
  2350                              <1>      ;2:
  2351                              <1>         ;;jmp	sysret
  2352                              <1> 		; jmp sysret / return to user
  2353                              <1> 
  2354                              <1> isintr:
  2355                              <1> 	; 03/02/2022
  2356                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2357                              <1> 	;
  2358                              <1> 	; 09/05/2013 - 30/05/2014
  2359                              <1> 	;
  2360                              <1> 	; Retro UNIX 8086 v1 modification !
  2361                              <1> 	; (Process/task switching and quit routine by using
  2362                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2363                              <1> 	;
  2364                              <1> 	; Retro UNIX 8086 v1 modification:
  2365                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2366                              <1> 	;  and there is a 'quit' request by user;
  2367                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2368                              <1> 	;  "nothing to do". (20/10/2013)
  2369                              <1> 	;
  2370                              <1> 	; 20/10/2013
  2371 00005056 66833D[8C700000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2372 0000505E 761F                <1> 	jna	short isintr2 ; retn
  2373                              <1> 	; 03/09/2013
  2374                              <1> 	; (nothing to do)
  2375                              <1> 	;retn
  2376                              <1> 	; 22/09/2013
  2377 00005060 66833D[9A700000]00  <1> 	cmp	word [u.intr], 0
  2378 00005068 7615                <1> 	jna	short isintr2 ; retn
  2379                              <1> 	; 30/05/2014
  2380                              <1> 	;push	ax
  2381                              <1> 	; 03/02/2022
  2382 0000506A 50                  <1> 	push	eax
  2383 0000506B 66A1[9C700000]      <1> 	mov	ax, [u.quit]
  2384 00005071 6609C0              <1> 	or	ax, ax ; 0 ?
  2385 00005074 7408                <1> 	jz	short isintr1 ; zf = 1
  2386 00005076 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2387 0000507A 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2388                              <1> 	;xor	ax, ax ; zf = 1
  2389                              <1> 	; 03/02/2022
  2390 0000507C 31C0                <1> 	xor	eax, eax ; zf = 1
  2391                              <1> isintr1:
  2392                              <1> 	;pop	ax
  2393                              <1> 	; 03/02/2022
  2394 0000507E 58                  <1> 	pop	eax
  2395                              <1> isintr2: ; 22/09/2013
  2396                              <1> 	; zf=1 -> nothing to do
  2397 0000507F C3                  <1> 	retn
  2398                              <1> 
  2399                              <1> 	; UNIX v1 original 'isintr' routine... 
  2400                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2401                              <1>        	;mov     r2,-(sp) / save r2
  2402                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2403                              <1>         ;                 / typewriter
  2404                              <1>        	;beq     1f / if 0, do nothing except skip return
  2405                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2406                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2407                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2408                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2409                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2410                              <1>         ;              / of interrupts
  2411                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2412                              <1>      ;1:
  2413                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2414                              <1>      ;4:
  2415                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2416                              <1>        	;mov     (sp)+,r1
  2417                              <1>        	;rts     r0
  2418                              <1>      ;3: / interrupt char = quit (fs)
  2419                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2420                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2421                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2422                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2423                              <1>      ;1: / find process control tty entry in tty block
  2424                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2425                              <1>        	;beq     1f / block found go to 1f
  2426                              <1>        	;add     $8,r1 / look at next tty block
  2427                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2428                              <1>        	;blo     1b / no
  2429                              <1>        	;br      4b / no process control tty found so go to 4b
  2430                              <1>      ;1:
  2431                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2432                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2433                              <1>         ;                  / identifier
  2434                              <1>        	;inc     0f / increment
  2435                              <1>      ;1:
  2436                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2437                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2438                              <1>         ;             / being typed out after you hit the interrupt
  2439                              <1>         ;             / key
  2440                              <1>        	;br      1b
  2052                                  %include 'u5.s'        ; 03/06/2015
  2053                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC
  2054                              <1> ; Last Modification: 22/04/2022
  2055                              <1> ; ----------------------------------------------------------------------------
  2056                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2057                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2058                              <1> ;
  2059                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2060                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2061                              <1> ; <Bell Laboratories (17/3/1972)>
  2062                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2063                              <1> ;
  2064                              <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2065                              <1> ;
  2066                              <1> ; ****************************************************************************
  2067                              <1> ; 14/11/2015
  2068                              <1> 
  2069                              <1> mget:
  2070                              <1> 	; 22/04/2022
  2071                              <1> 	; 03/02/2022
  2072                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2073                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2074                              <1> 	;
  2075                              <1> 	; Get existing or (allocate) a new disk block for file
  2076                              <1> 	; 
  2077                              <1> 	; INPUTS ->
  2078                              <1> 	;    u.fofp (file offset pointer)
  2079                              <1> 	;    inode 
  2080                              <1> 	;    u.off (file offset)
  2081                              <1> 	; OUTPUTS ->
  2082                              <1> 	;    r1 (physical block number)
  2083                              <1> 	;    r2, r3, r5 (internal)
  2084                              <1> 	;
  2085                              <1> 	; ((AX = R1)) output
  2086                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2087                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2088                              <1> 
  2089                              <1> 		; mov *u.fofp,mq / file offset in mq
  2090                              <1> 		; clr ac / later to be high sig
  2091                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2092                              <1> 		; mov mq,r2
  2093                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2094                              <1> 		; bne 4f / branch for large file
  2095                              <1> mget_0:	
  2096                              <1> 	; 03/02/2022
  2097 00005080 29C0                <1> 	sub	eax, eax
  2098 00005082 29D2                <1> 	sub	edx, edx
  2099 00005084 29C9                <1> 	sub	ecx, ecx
  2100 00005086 29DB                <1> 	sub	ebx, ebx
  2101                              <1> 
  2102 00005088 8B35[6C700000]      <1>         mov     esi, [u.fofp]
  2103                              <1>         ;movzx	ebx, byte [esi+1]
  2104                              <1> 	; 03/02/2022
  2105 0000508E 46                  <1> 	inc	esi
  2106 0000508F 8A1E                <1> 	mov	bl, [esi]
  2107                              <1> 
  2108                              <1> 	; BX = r2
  2109                              <1> 	; 03/02/2022
  2110 00005091 F605[596D0000]10    <1> 	test	byte [i.flgs+1], 10h
  2111                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2112                              <1> 			  	     ; is this a large or small file
  2113 00005098 756C                <1> 	jnz 	short mget_5 ; 4f ; large file
  2114                              <1> 
  2115 0000509A F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2116                              <1> 		; bit $!17,r2
  2117 0000509D 7525                <1> 	jnz 	short mget_2
  2118                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2119 0000509F 80E30E              <1>         and     bl, 0Eh  
  2120                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2121                              <1> 	; 03/02/2022
  2122 000050A2 668B83[5E6D0000]    <1> 	mov	ax, [ebx+i.dskp]
  2123                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2124                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2125                              <1> 	; 03/02/2022
  2126 000050A9 09C0                <1> 	or	eax, eax
  2127                              <1> 	;or 	ax, ax
  2128 000050AB 7516                <1> 	jnz 	short mget_1 
  2129                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2130                              <1> 		       ; / for file
  2131 000050AD E8A6000000          <1> 	call 	alloc
  2132                              <1> 		; jsr r0,alloc / allocate a new block
  2133                              <1>          ; eAX (r1) = Physical block number
  2134 000050B2 668983[5E6D0000]    <1> 	mov 	[ebx+i.dskp], ax
  2135                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2136 000050B9 E835020000          <1> 	call 	setimod	
  2137                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2138 000050BE E8C2FEFFFF          <1> 	call	clear
  2139                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2140                              <1> mget_1: ; 2:
  2141                              <1>         ; eAX (r1) = Physical block number
  2142 000050C3 C3                  <1> 	retn 
  2143                              <1> 		; rts r0
  2144                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2145 000050C4 E88F000000          <1> 	call 	alloc
  2146                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2147                              <1> 	                     ; / block number in r1
  2148                              <1>         ; eAX (r1) = Physical block number
  2149 000050C9 E85E0D0000          <1> 	call 	wslot
  2150                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2151                              <1> 			     ; / first data word in buffer
  2152                              <1>         ; 03/02/2022
  2153 000050CE 31C9                <1> 	xor	ecx, ecx
  2154 000050D0 B108                <1> 	mov	cl, 8
  2155                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2156                              <1> 		   ; into new indirect block area for the new
  2157                              <1> 		   ; large file		
  2158 000050D2 89DF                <1> 	mov 	edi, ebx ; r5
  2159 000050D4 BE[5E6D0000]        <1> 	mov 	esi, i.dskp 
  2160                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2161                              <1> 			   ; / block pointers
  2162                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2163                              <1> 			  ; / large file
  2164                              <1> 	; 22/04/2022
  2165 000050D9 50                  <1> 	push	eax ; * ; bugfix
  2166                              <1> 
  2167                              <1> 	;xor 	ax, ax ; mov ax, 0
  2168                              <1> 	; 03/02/2022
  2169 000050DA 31C0                <1> 	xor	eax, eax
  2170                              <1> mget_3: ;1:
  2171 000050DC 66A5                <1> 	movsw
  2172                              <1> 		; mov (r2),(r5)+
  2173 000050DE 668946FE            <1> 	mov 	[esi-2], ax
  2174                              <1> 		; clr (r2)+
  2175 000050E2 E2F8                <1> 	loop	mget_3 ; 1b
  2176                              <1> 		; dec r3
  2177                              <1> 		; bgt 1b
  2178                              <1> 
  2179 000050E4 B1F8                <1> 	mov 	cl, 256-8
  2180                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2181                              <1> mget_4:	; 1
  2182 000050E6 F366AB              <1> 	rep 	stosw
  2183                              <1> 		; clr (r5)+
  2184                              <1> 		; dec r3
  2185                              <1> 		; bgt 1b
  2186                              <1> 	
  2187                              <1> 	; 22/04/2022
  2188                              <1> 	;pop	eax ; * ; bugfix
  2189                              <1> 
  2190                              <1> 	; 24/03/2013
  2191                              <1>         ; AX (r1) = Physical block number
  2192 000050E9 E85A0D0000          <1> 	call	dskwr
  2193                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2194                              <1> 
  2195                              <1> 	; 22/04/2022
  2196 000050EE 58                  <1> 	pop	eax ; * ; bugfix
  2197                              <1> 
  2198                              <1>         ; eAX (r1) = Physical block number
  2199 000050EF 66A3[5E6D0000]      <1> 	mov 	[i.dskp], ax
  2200                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2201                              <1> 	; 03/02/2022
  2202 000050F5 800D[596D0000]10    <1> 	or	byte [i.flgs+1], 10h
  2203                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2204                              <1> 		; bis $10000,i.flgs / set large file bit 
  2205                              <1> 				  ; / in i.flgs word of i-node
  2206 000050FC E8F2010000          <1> 	call	setimod
  2207                              <1> 		; jsr r0,setimod / set i-node modified flag
  2208 00005101 E97AFFFFFF          <1>         jmp     mget_0 
  2209                              <1> 		; br mget
  2210                              <1> 
  2211                              <1> mget_5:  ; 4 ; large file
  2212                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2213                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2214                              <1> 			    ; / in indirect block
  2215                              <1> 		; mov r2,-(sp) / save on stack (*)
  2216                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2217                              <1>        		          ; / indirect block
  2218                              <1> 		; bic $!16,r2
  2219 00005106 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2220 00005109 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2221                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2222                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2223                              <1> 	; There is always 1 indirect block for this file system
  2224                              <1> 	; 03/02/2022
  2225 0000510A 66A1[5E6D0000]      <1> 	mov	ax, [i.dskp]
  2226                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2227                              <1> 		; mov i.dskp(r2),r1
  2228                              <1> 	; 03/02/2022
  2229 00005110 09C0                <1> 	or	eax, eax
  2230                              <1> 	;or 	ax, ax ; R1
  2231 00005112 7515                <1> 	jnz 	short mget_6 ; 2f
  2232                              <1> 		; bne 2f / if no indirect block exists
  2233 00005114 E83F000000          <1> 	call 	alloc
  2234                              <1> 		; jsr r0,alloc / allocate a new block
  2235 00005119 66A3[5E6D0000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2236                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2237 0000511F E8CF010000          <1> 	call 	setimod
  2238                              <1> 		; jsr r0,setimod / set i-node modified byte
  2239                              <1> 	; eAX = new block number
  2240 00005124 E85CFEFFFF          <1> 	call 	clear
  2241                              <1> 		; jsr r0,clear / clear new block
  2242                              <1> mget_6: ;2
  2243                              <1> 	; 05/03/2013
  2244                              <1> 	; eAX = r1, physical block number (of indirect block)
  2245 00005129 E88C0C0000          <1> 	call 	dskrd ; read indirect block
  2246                              <1> 		; jsr r0,dskrd / read in indirect block
  2247 0000512E 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2248                              <1> 		; mov (sp)+,r2 / get offset
  2249                              <1> 	; eAX = r1, physical block number (of indirect block)
  2250 0000512F 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2251                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2252                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2253 00005130 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2254                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2255                              <1> 	                  ; / points to location of inter
  2256                              <1> 	; 03/02/2022
  2257 00005132 668B03              <1> 	mov	ax, [ebx]
  2258                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2259                              <1> 			      ; in file sought in R1 (AX)
  2260                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2261                              <1> 	               	    ; / sought in r1
  2262                              <1> 	; 03/02/2022
  2263 00005135 09C0                <1> 	or	eax, eax
  2264                              <1> 	;or 	ax, ax
  2265 00005137 751D                <1>         jnz 	short mget_7 ; 2f
  2266                              <1> 		; bne 2f / if no block exists 
  2267 00005139 E81A000000          <1> 	call 	alloc
  2268                              <1> 		; jsr r0,alloc / allocate a new block
  2269 0000513E 668903              <1> 	mov 	[ebx], ax ; R1
  2270                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2271                              <1> 	                    ; / indirect block
  2272 00005141 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2273                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2274 00005142 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2275 00005143 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2276 00005144 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2277                              <1> 		; mov (r2),-(sp) / save block number of new block
  2278                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2279 00005146 E8E10C0000          <1> 	call 	wslot
  2280                              <1> 		; jsr r0,wslot
  2281                              <1>         ; eAX (r1) = physical block number
  2282                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2283 0000514B E8F80C0000          <1> 	call 	dskwr
  2284                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2285                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2286                              <1> 			     ; / back out on disk
  2287 00005150 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2288                              <1> 		; mov (sp),r1 / restore block number of new block	
  2289                              <1> 	; eAX (r1) = physical block number of new block
  2290 00005151 E82FFEFFFF          <1> 	call 	clear
  2291                              <1> 		; jsr r0,clear / clear new block	
  2292                              <1> mget_7: ; 2
  2293 00005156 5A                  <1> 	pop 	edx ; **
  2294                              <1> 		; tst (sp)+ / bump stack pointer
  2295                              <1> 	; eAX (r1) = Block number of new block
  2296 00005157 C3                  <1> 	retn
  2297                              <1> 		; rts r0
  2298                              <1> 
  2299                              <1> alloc:
  2300                              <1> 	; 03/02/2022
  2301                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2302                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2303                              <1> 	;
  2304                              <1> 	; get a free block and 
  2305                              <1> 	; set the corresponding bit in the free storage map
  2306                              <1> 	; 
  2307                              <1> 	; INPUTS ->
  2308                              <1> 	;    cdev (current device)
  2309                              <1> 	;    r2 
  2310                              <1> 	;    r3
  2311                              <1> 	; OUTPUTS ->
  2312                              <1> 	;    r1 (physical block number of block assigned)
  2313                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2314                              <1> 	;
  2315                              <1> 	; ((AX = R1)) output
  2316                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2317                              <1>         ;    ((Modified registers: DX, CX))  
  2318                              <1> 
  2319                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2320                              <1> 		;mov r3,-(sp)
  2321                              <1> 	;push 	ecx
  2322 00005158 53                  <1> 	push 	ebx ; R2
  2323                              <1> 	;push 	edx ; R3
  2324 00005159 BB[147D0000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2325                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2326 0000515E 803D[40700000]00    <1> 	cmp 	byte [cdev], 0
  2327                              <1> 		; tst cdev
  2328 00005165 7605                <1> 	jna	short alloc_1
  2329                              <1> 		; beq 1f / drum is device
  2330 00005167 BB[1C7F0000]        <1> 	mov	ebx, mount
  2331                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2332                              <1> 			      ; / free storage map
  2333                              <1> alloc_1: ; 1
  2334                              <1> 	; 03/02/2022
  2335                              <1> 	;sub	ecx, ecx
  2336                              <1> 	;sub	edx, edx
  2337                              <1> 	;sub	eax, eax
  2338                              <1> 
  2339 0000516C 668B0B              <1>         mov	cx, [ebx]
  2340                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2341                              <1> 			     ; / storage map
  2342                              <1> 	; 03/02/2022
  2343 0000516F C1E103              <1> 	shl	ecx, 3
  2344                              <1> 	;shl	cx, 3
  2345                              <1> 		; asl r1 / multiply r1 by eight gives 
  2346                              <1> 		; number of blocks in device
  2347                              <1> 		; asl r1
  2348                              <1> 		; asl r1
  2349                              <1> 	;;push	cx ;; 01/08/2013
  2350                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2351 00005172 31C0                <1> 	xor 	eax, eax ; 0
  2352                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2353                              <1> alloc_2: ; 1
  2354 00005174 43                  <1> 	inc 	ebx ; 18/8/2012
  2355 00005175 43                  <1> 	inc 	ebx ; 
  2356 00005176 668B13              <1> 	mov 	dx, [ebx]
  2357                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2358                              <1> 	; 03/02/2022
  2359 00005179 09D2                <1> 	or	edx, edx
  2360                              <1> 	;or 	dx, dx
  2361 0000517B 750D                <1> 	jnz 	short alloc_3 ; 1f
  2362                              <1> 		; bne 1f / branch if any free blocks in this word	
  2363 0000517D 6683C010            <1> 	add 	ax, 16
  2364                              <1> 		; add $16.,r1
  2365                              <1> 	; 03/02/2022
  2366 00005181 39C8                <1> 	cmp	eax, ecx
  2367                              <1> 	;cmp 	ax, cx    
  2368                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2369 00005183 72EF                <1> 	jb 	short alloc_2
  2370                              <1> 		; blo 1b
  2371                              <1> 	; 14/11/2015
  2372                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2373                              <1> 	;	because of a (DMA or another) r/w error, 
  2374                              <1> 	;	we will be here, at 'jmp panic' code address,
  2375                              <1> 	;	even if the (disk) file system space is not full !!!
  2376                              <1> 	;	(cx = 0)	
  2377                              <1> 	;
  2378 00005185 E908E2FFFF          <1> 	jmp     panic 
  2379                              <1> 		; jmp panic / found no free storage
  2380                              <1> alloc_3: ; 1
  2381                              <1> 	; 03/02/2022
  2382 0000518A D1EA                <1> 	shr	edx, 1
  2383                              <1> 	;shr	dx, 1
  2384                              <1> 		; asr r3 / find a free block
  2385 0000518C 7203                <1> 	jc	short alloc_4 ; 1f
  2386                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2387                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2388                              <1> 	; 03/02/2022
  2389 0000518E 40                  <1> 	inc	eax
  2390                              <1> 	;inc	ax
  2391                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2392 0000518F EBF9                <1> 	jmp 	short alloc_3
  2393                              <1> 		; br 1b
  2394                              <1> alloc_4: ; 1:
  2395                              <1> 	;; pop cx ;; 01/08/2013
  2396                              <1> 		; tst (sp)+ / bump sp
  2397                              <1> 	; 02/04/2013 
  2398 00005191 E829000000          <1> 	call	free3
  2399                              <1> 		; jsr r0,3f / have found a free block
  2400                              <1> 	; 21/8/2012
  2401 00005196 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2402 00005199 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2403                              <1> 		; bic r3,(r2) / set bit for this block 
  2404                              <1> 		            ; / i.e. assign block
  2405                              <1> 		; br 2f
  2406 0000519C EB09                <1> 	jmp 	short alloc_5
  2407                              <1> 
  2408                              <1> free:
  2409                              <1> 	; 03/02/2022
  2410                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2411                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2412                              <1> 	;
  2413                              <1> 	; calculates byte address and bit position for given block number
  2414                              <1> 	; then sets the corresponding bit in the free storage map
  2415                              <1> 	; 
  2416                              <1> 	; INPUTS ->
  2417                              <1> 	;    r1 - block number for a block structured device
  2418                              <1> 	;    cdev - current device 
  2419                              <1> 	; OUTPUTS ->
  2420                              <1> 	;    free storage map is updated
  2421                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2422                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2423                              <1> 	;
  2424                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2425                              <1>         ;  ((Modified registers: DX, CX))  
  2426                              <1> 
  2427                              <1> 		;mov r2,-(sp) / save r2, r3
  2428                              <1> 		;mov r3,-(sp)
  2429                              <1> 	;push 	ecx
  2430 0000519E 53                  <1> 	push 	ebx ; R2
  2431                              <1> 	;push 	edx ; R3 
  2432                              <1> 
  2433 0000519F E81B000000          <1>         call    free3
  2434                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2435                              <1> 				 ; / in free storage map for block
  2436 000051A4 660913              <1> 	or 	[ebx], dx  
  2437                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2438                              <1> 			    ;  / indicates free block	
  2439                              <1> 	; 0 -> allocated, 1 -> free
  2440                              <1> 
  2441                              <1> alloc_5:
  2442                              <1> 	; 07/04/2013
  2443                              <1> free_1: ; 2:
  2444                              <1> 	;pop 	edx
  2445                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2446 000051A7 5B                  <1> 	pop	ebx
  2447                              <1> 		; mov (sp)+,r2
  2448                              <1> 	; pop	ecx
  2449 000051A8 803D[40700000]00    <1> 	cmp 	byte [cdev], 0
  2450                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2451                              <1> 			 ; / cdev = 1, mountable device
  2452 000051AF 7707                <1> 	ja	short alloc_6 ; 1f
  2453                              <1> 		; bne 1f
  2454                              <1> 	;mov	byte [smod], 1
  2455 000051B1 FE05[51700000]      <1> 	inc 	byte [smod]
  2456                              <1> 		; incb smod / set super block modified for drum
  2457                              <1> 	; eAX (r1) = block number
  2458 000051B7 C3                  <1> 	retn
  2459                              <1> 		; rts r0
  2460                              <1> free_2:
  2461                              <1> alloc_6: ; 1:
  2462                              <1> 	;mov 	byte [mmod], 1
  2463 000051B8 FE05[52700000]      <1> 	inc 	byte [mmod]
  2464                              <1> 		; incb	mmod 
  2465                              <1> 		  ; / set super block modified for mountable device
  2466                              <1> 	; eAX (r1) = block number
  2467 000051BE C3                  <1> 	retn	
  2468                              <1> 		; rts r0
  2469                              <1> free3:
  2470                              <1> 	; 03/02/2022
  2471                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2472                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2473                              <1> 	;
  2474                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2475                              <1> 	; 
  2476                              <1> alloc_free_3: ; 3
  2477                              <1> 	;mov 	dx, 1
  2478                              <1> 	; 03/02/2022
  2479 000051BF 31D2                <1> 	xor	edx, edx
  2480 000051C1 42                  <1> 	inc	edx
  2481                              <1> 	; edx = 1
  2482 000051C2 88C1                <1> 	mov 	cl, al
  2483                              <1> 		; mov r1,r2 / block number, k, = 1		
  2484 000051C4 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2485                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2486 000051C7 7402                <1> 	jz 	short free4
  2487                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2488                              <1> 			       ; / (k) mod 8
  2489                              <1> 	;shl 	dx, cl
  2490                              <1> 	; 03/02/2022
  2491 000051C9 D3E2                <1> 	shl	edx, cl
  2492                              <1> free4:
  2493 000051CB 0FB7D8              <1> 	movzx 	ebx, ax
  2494                              <1> 		; mov r1,r2 / divide block number by 16
  2495                              <1> 	; 03/02/2022
  2496 000051CE C1EB04              <1> 	shr	ebx, 4
  2497                              <1> 	;shr 	bx, 4
  2498                              <1> 		; asr r2
  2499                              <1> 		; asr r2
  2500                              <1> 		; asr r2
  2501                              <1> 		; asr r2
  2502                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2503                              <1> 		       ; / bit for block is in lower half of word
  2504                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2505                              <1> 		        ; / storage map
  2506                              <1> alloc_free_4: ; 1
  2507                              <1> 	; 03/02/2022
  2508 000051D1 D1E3                <1> 	shl	ebx, 1
  2509                              <1> 	;shl 	bx, 1
  2510                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2511 000051D3 81C3[167D0000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2512                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2513                              <1> 	    		        ; / with block bit in it 	
  2514 000051D9 803D[40700000]00    <1> 	cmp	byte [cdev], 0
  2515                              <1> 		; tst cdev
  2516 000051E0 7606                <1> 	jna	short alloc_free_5
  2517                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2518 000051E2 81C308020000        <1> 	add	ebx, mount - systm
  2519                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2520                              <1> 				    ; / mountable device with bit of block to be
  2521                              <1> 				    ; / freed
  2522                              <1> alloc_free_5: ; 1 
  2523 000051E8 C3                  <1> 	retn
  2524                              <1> 		; rts r0 / return to 'free'
  2525                              <1> 	      ; 2
  2526                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2527                              <1> 	
  2528                              <1> iget:
  2529                              <1> 	; 03/02/2022
  2530                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2531                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2532                              <1> 	;
  2533                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2534                              <1> 	;
  2535                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2536                              <1> 	; 
  2537                              <1> 	; INPUTS ->
  2538                              <1> 	;    ii - current i-number, rootdir
  2539                              <1> 	;    cdev - new i-node device
  2540                              <1> 	;    idev - current i-node device
  2541                              <1> 	;    imod - current i-node modified flag
  2542                              <1> 	;    mnti - cross device file i-number
  2543                              <1> 	;    r1 - i-numbe rof new i-node
  2544                              <1> 	;    mntd - mountable device number		
  2545                              <1> 	; 	 
  2546                              <1> 	; OUTPUTS ->
  2547                              <1> 	;    cdev, idev, imod, ii, r1
  2548                              <1> 	;
  2549                              <1> 	; ((AX = R1)) input/output
  2550                              <1> 	;
  2551                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2552                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2553                              <1> 
  2554 000051E9 8A15[40700000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2555 000051EF 8A35[3E700000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2556                              <1> 	;
  2557 000051F5 663B05[3C700000]    <1> 	cmp 	ax, [ii]
  2558                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2559 000051FC 7504                <1> 	jne 	short iget_1
  2560                              <1> 		; bne 1f
  2561 000051FE 38F2                <1> 	cmp	dl, dh
  2562                              <1> 		; cmp idev,cdev
  2563                              <1> 			  ; / is device number of i-node = current device
  2564 00005200 7472                <1>         je      short iget_5
  2565                              <1> 		; beq 2f
  2566                              <1> iget_1: ; 1:
  2567 00005202 30DB                <1> 	xor	bl, bl
  2568 00005204 381D[50700000]      <1> 	cmp	[imod], bl ; 0	
  2569                              <1> 		; tstb imod / has i-node of current file
  2570                              <1> 			  ; / been modified i.e., imod set
  2571 0000520A 7629                <1> 	jna	short iget_2
  2572                              <1> 		; beq 1f
  2573 0000520C 881D[50700000]      <1> 	mov	[imod], bl ; 0
  2574                              <1> 		;  clrb	imod / if it has, 
  2575                              <1> 			   ; / we must write the new i-node out on disk
  2576                              <1> 	; 03/02/2022
  2577 00005212 50                  <1> 	push	eax ; *
  2578                              <1> 	;push	ax
  2579                              <1> 		; mov r1,-(sp)
  2580                              <1> 	;mov	dl, [cdev]
  2581 00005213 52                  <1> 	push	edx ; **
  2582                              <1> 	;push	dx
  2583                              <1> 		; mov cdev,-(sp)
  2584 00005214 66A1[3C700000]      <1> 	mov	ax, [ii]
  2585                              <1> 		; mov ii,r1
  2586                              <1> 	;mov	dh, [idev]
  2587 0000521A 8835[40700000]      <1> 	mov	[cdev], dh
  2588                              <1> 		; mov idev,cdev
  2589 00005220 FEC3                <1> 	inc	bl ; 1
  2590                              <1> 	; 31/07/2013
  2591 00005222 881D[D8700000]      <1> 	mov     [rw], bl ; 1 == write 
  2592                              <1> 	;;28/07/2013 rw -> u.rw
  2593                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2594 00005228 E848000000          <1> 	call	icalc
  2595                              <1> 		; jsr r0,icalc; 1
  2596                              <1> 	;pop	dx
  2597                              <1> 	; 03/02/2022
  2598 0000522D 5A                  <1> 	pop	edx ; **
  2599 0000522E 8815[40700000]      <1> 	mov	[cdev], dl
  2600                              <1> 		; mov (sp)+,cdev
  2601                              <1> 	; 03/02/2022
  2602 00005234 58                  <1> 	pop	eax ; *
  2603                              <1> 	;pop	ax
  2604                              <1> 		; mov (sp)+,r1
  2605                              <1> iget_2: ; 1:
  2606 00005235 6621C0              <1> 	and	ax, ax
  2607                              <1> 		; tst r1 / is new i-number non zero
  2608 00005238 7434                <1> 	jz	short iget_4 ; 2f
  2609                              <1> 		; beq 2f / branch if r1=0
  2610                              <1> 
  2611                              <1> 	;mov 	dl, [cdev]
  2612 0000523A 08D2                <1> 	or	dl, dl
  2613                              <1> 		; tst cdev / is the current device number non zero
  2614                              <1> 			 ; / (i.e., device =/ drum)
  2615 0000523C 7517                <1> 	jnz	short iget_3 ;  1f
  2616                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2617 0000523E 663B05[46700000]    <1> 	cmp	ax, [mnti]			
  2618                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2619                              <1> 			    ; / file (root directory of mounted device)
  2620 00005245 750E                <1> 	jne	short iget_3 ; 1f
  2621                              <1> 		; bne 1f
  2622                              <1>         ;mov    bl, [mntd]
  2623 00005247 FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2624 00005249 8815[40700000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2625                              <1> 		; mov mntd,cdev / make mounted device the current device
  2626 0000524F 66A1[4C700000]      <1> 	mov	ax, [rootdir]
  2627                              <1> 		; mov rootdir,r1
  2628                              <1> iget_3: ; 1:
  2629 00005255 66A3[3C700000]      <1> 	mov	[ii], ax
  2630                              <1> 		; mov r1,ii
  2631 0000525B 8815[3E700000]      <1> 	mov	[idev], dl ; cdev
  2632                              <1> 		; mov cdev,idev
  2633 00005261 30DB                <1> 	xor	bl, bl
  2634                              <1>         ; 31/07/2013
  2635 00005263 881D[D8700000]      <1> 	mov     [rw], bl ; 0 == read 
  2636                              <1> 	;;28/07/2013 rw -> u.rw       
  2637                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2638 00005269 E807000000          <1> 	call	icalc
  2639                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2640                              <1> iget_4: ; 2:
  2641 0000526E 66A1[3C700000]      <1> 	mov	ax, [ii]
  2642                              <1> 		; mov ii,r1
  2643                              <1> iget_5:
  2644 00005274 C3                  <1> 	retn
  2645                              <1> 		; rts r0
  2646                              <1> 
  2647                              <1> icalc:
  2648                              <1> 	; 04/04/2022 (47->31)
  2649                              <1> 	;	(Inode Table/List Address modification)
  2650                              <1> 	; 03/02/2022
  2651                              <1> 	; 02/07/2015
  2652                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2653                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2654                              <1> 	;
  2655                              <1> 	; calculate physical block number from i-number then
  2656                              <1> 	; read or write that block
  2657                              <1> 	;
  2658                              <1> 	; 'icalc' is called from 'iget'
  2659                              <1> 	;
  2660                              <1> 	; for original unix v1:
  2661                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2662                              <1>        	; / (i+31.) mod 16. bytes from its start
  2663                              <1> 	;
  2664                              <1> 	; for retro unix 8086 v1:
  2665                              <1> 	;  i-node is located in block (i+47)/16 and
  2666                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2667                              <1> 	;
  2668                              <1> 	; INPUTS ->
  2669                              <1> 	;    r1 - i-number of i-node
  2670                              <1> 	; 	 
  2671                              <1> 	; OUTPUTS ->
  2672                              <1> 	;    inode r/w
  2673                              <1> 	;
  2674                              <1> 	; ((AX = R1)) input
  2675                              <1> 	;
  2676                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2677                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2678                              <1> 	;
  2679 00005275 0FB7D0              <1> 	movzx	edx, ax	
  2680                              <1> 	;add	dx, 47
  2681                              <1> 	; 04/04/2022
  2682 00005278 6683C21F            <1> 	add	dx, 31
  2683 0000527C 89D0                <1> 	mov	eax, edx
  2684                              <1> 	;;add	ax, 47	; add 47 to inode number
  2685                              <1> 	;add	ax, 31
  2686                              <1> 		; add $31.,r1 / add 31. to i-number
  2687 0000527E 50                  <1> 	push	eax
  2688                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2689                              <1> 	; 03/02/2022
  2690 0000527F C1E804              <1> 	shr	eax, 4
  2691                              <1> 	;shr 	ax, 4
  2692                              <1> 		; asr r1 / divide by 16.
  2693                              <1> 		; asr r1
  2694                              <1> 		; asr r1
  2695                              <1> 		; asr r1 / r1 contains block number of block
  2696                              <1> 		       ; / in which i-node exists
  2697 00005282 E8330B0000          <1> 	call	dskrd
  2698                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2699                              <1> 	; 31/07/2013
  2700 00005287 803D[D8700000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2701                              <1> 	;; 28/07/2013 rw -> u.rw
  2702                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2703                              <1> 		; tst (r0)
  2704 0000528E 7605                <1> 	jna	short icalc_1
  2705                              <1> 		; beq 1f / branch to wslot when argument
  2706                              <1> 		       ; / in icalc call = 1
  2707                              <1> 	; eAX = r1 = block number
  2708 00005290 E8970B0000          <1> 	call	wslot
  2709                              <1> 		; jsr r0,wslot / set up data buffer for write
  2710                              <1> 			     ; / (will be same buffer as dskrd got)
  2711                              <1> 	; eBX = r5 points to first word in data area for this block
  2712                              <1> icalc_1: ; 1:
  2713 00005295 5A                  <1> 	pop	edx 
  2714 00005296 83E20F              <1> 	and 	edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16
  2715                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2716                              <1> 			      ; / gives (i+31.) mod 16
  2717 00005299 C1E205              <1> 	shl 	edx, 5
  2718                              <1> 	; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16)
  2719 0000529C 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2720 0000529E 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2721                              <1>           	; eSI (r5) points to first word in i-node i.	
  2722                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2723                              <1> 			     ; / 32.*(i+31.)mod16
  2724                              <1> 		; mov $5,lsh / for i-node i.
  2725                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2726 000052A0 BF[586D0000]        <1> 	mov	edi, inode
  2727                              <1> 		; mov $inode,r1 / inode is address of first word 
  2728                              <1> 			      ; / of current i-node
  2729                              <1> 	; 03/02/2022
  2730 000052A5 29C9                <1> 	sub	ecx, ecx
  2731 000052A7 B108                <1> 	mov	cl, 8 
  2732                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2733                              <1> 		; mov $16.,r3
  2734                              <1>         ; 31/07/2013
  2735 000052A9 382D[D8700000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2736                              <1>        ;;28/07/2013 rw -> u.rw                 
  2737                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2738                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2739 000052AF 7609                <1> 	jna	short icalc_3
  2740                              <1> 		; beq 2f / r0 now contains proper return address 
  2741                              <1> 		       ; / for rts r0
  2742                              <1> icalc_2: ; 1:
  2743 000052B1 87F7                <1> 	xchg 	esi, edi
  2744                              <1> 	; overwrite old i-node (in buffer to be written)
  2745 000052B3 F3A5                <1> 	rep 	movsd
  2746                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2747                              <1> 		; dec r3
  2748                              <1> 		; bgt 1b
  2749                              <1> 	;call	dskwr
  2750                              <1> 		; jsr r0,dskwr / write inode out on device
  2751                              <1> 	;retn
  2752                              <1> 		; rts r0
  2753                              <1> 	; 03/02/2022
  2754 000052B5 E98E0B0000          <1> 	jmp	dskwr
  2755                              <1> icalc_3: ; 2:
  2756                              <1> 	; copy new i-node into inode area of (core) memory
  2757 000052BA F3A5                <1> 	rep 	movsd
  2758                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2759                              <1> 		                ; / "inode" area of core
  2760                              <1> 		; dec r3
  2761                              <1> 		; bgt 2b
  2762 000052BC C3                  <1> 	retn
  2763                              <1> 		; rts r0
  2764                              <1> 
  2765                              <1> access:
  2766                              <1> 	; 03/02/2022
  2767                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2768                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2769                              <1> 	;
  2770                              <1> 	; check whether user is owner of file or user has read or write
  2771                              <1> 	; permission (based on i.flgs).
  2772                              <1> 	;
  2773                              <1> 	; INPUTS ->
  2774                              <1> 	;    r1 - i-number of file
  2775                              <1> 	;    u.uid
  2776                              <1> 	; arg0 -> (owner flag mask)	 		
  2777                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2778                              <1> 	; OUTPUTS ->
  2779                              <1> 	;    inode (or jump to error)
  2780                              <1> 	;
  2781                              <1> 	; ((AX = R1)) input/output
  2782                              <1> 	;
  2783                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2784                              <1> 	;
  2785                              <1> 
  2786                              <1> 	;push	dx  ; save flags (DL)
  2787                              <1> 	; 03/02/2022
  2788 000052BD 52                  <1> 	push	edx ; save flags (DL)
  2789 000052BE E826FFFFFF          <1> 	call	iget
  2790                              <1> 		; jsr r0,iget / read in i-node for current directory
  2791                              <1> 			    ; / (i-number passed in r1)
  2792 000052C3 8A0D[586D0000]      <1> 	mov	cl, [i.flgs]
  2793                              <1> 		; mov i.flgs,r2
  2794                              <1> 	; 03/02/2022
  2795 000052C9 5A                  <1> 	pop	edx ; restore flags (DL)
  2796                              <1> 	;pop	dx  ; restore flags (DL)
  2797 000052CA 8A35[A2700000]      <1> 	mov	dh, [u.uid]
  2798 000052D0 3A35[5B6D0000]      <1> 	cmp	dh, [i.uid]
  2799                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2800 000052D6 7503                <1> 	jne	short access_1
  2801                              <1> 		; bne 1f / no, then branch
  2802 000052D8 C0E902              <1> 	shr	cl, 2
  2803                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2804                              <1> 		        ; / read/write bits
  2805                              <1> 		; asrb r2
  2806                              <1> access_1: ; 1:
  2807 000052DB 20D1                <1> 	and	cl, dl
  2808                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2809                              <1> 			     ; / in access call
  2810 000052DD 7513                <1> 	jnz	short access_2
  2811                              <1> 		; bne 1f
  2812 000052DF 08F6                <1> 	or	dh, dh	; super user  (root) ?
  2813                              <1> 		; tstb u.uid
  2814 000052E1 740F                <1> 	jz	short access_2 ; yes, super user
  2815                              <1> 	;jnz	error
  2816                              <1> 		; beq 1f
  2817                              <1> 		; jmp error
  2818 000052E3 C705[AB700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2818 000052EB 0000                <1>
  2819                              <1> 			; 'permission denied !' error
  2820 000052ED E9E1E7FFFF          <1> 	jmp	error
  2821                              <1> 
  2822                              <1> access_2: ; 1:
  2823                              <1> 	; DL = flags
  2824 000052F2 C3                  <1> 	retn
  2825                              <1> 		; rts r0
  2826                              <1> 
  2827                              <1> setimod:
  2828                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2829                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2830                              <1> 	;
  2831                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2832                              <1> 	; the inode has been modified. Also puts the time of modification
  2833                              <1> 	; into the inode.
  2834                              <1> 	;
  2835                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2836                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  2837                              <1> 	;
  2838                              <1> 	
  2839                              <1> 	; push 	edx
  2840 000052F3 50                  <1> 	push	eax
  2841                              <1> 
  2842 000052F4 C605[50700000]01    <1> 	mov 	byte [imod], 1
  2843                              <1> 		; movb $1,imod / set current i-node modified bytes
  2844                              <1> 	; Erdogan Tan 14-7-2012
  2845 000052FB E821E3FFFF          <1> 	call 	epoch
  2846                              <1> 		 ; mov s.time,i.mtim 
  2847                              <1> 			    ; / put present time into file modified time
  2848                              <1> 		 ; mov s.time+2,i.mtim+2
  2849                              <1> 
  2850 00005300 A3[726D0000]        <1> 	mov 	[i.mtim], eax
  2851                              <1> 	
  2852                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2853                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2854 00005305 833D[6E6D0000]00    <1> 	cmp	dword [i.ctim], 0
  2855 0000530C 7505                <1> 	jnz	short setimod_ok
  2856                              <1> 
  2857 0000530E A3[6E6D0000]        <1> 	mov 	[i.ctim], eax
  2858                              <1> 
  2859                              <1> setimod_ok: ; 31/07/2013
  2860 00005313 58                  <1> 	pop	eax
  2861                              <1> 	;pop	edx
  2862                              <1> 	
  2863 00005314 C3                  <1> 	retn
  2864                              <1> 		; rts r0
  2865                              <1> 
  2866                              <1> itrunc:
  2867                              <1> 	; 03/02/2022
  2868                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2869                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2870                              <1> 	;
  2871                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2872                              <1> 	;  to zero length.
  2873                              <1> 	;
  2874                              <1> 	; INPUTS ->
  2875                              <1> 	;    r1 - i-number of i-node
  2876                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2877                              <1> 	;    i.flgs - large file flag		
  2878                              <1> 	;    i.size - size of file	
  2879                              <1> 	; 	 
  2880                              <1> 	; OUTPUTS ->
  2881                              <1> 	;    i.flgs - large file flag is cleared
  2882                              <1> 	;    i.size - set to 0	
  2883                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2884                              <1> 	;    setimod - set to indicate i-node has been modified
  2885                              <1> 	;    r1 - i-number of i-node  					
  2886                              <1> 	;
  2887                              <1> 	; ((AX = R1)) input/output
  2888                              <1> 	;
  2889                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2890                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2891                              <1> 
  2892 00005315 E8CFFEFFFF          <1> 	call	iget
  2893                              <1> 		; jsr r0,iget
  2894 0000531A BE[5E6D0000]        <1> 	mov	esi, i.dskp
  2895                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2896 0000531F 31C0                <1> 	xor	eax, eax
  2897                              <1> itrunc_1: ; 1:
  2898 00005321 66AD                <1> 	lodsw
  2899                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2900                              <1> 	; 03/02/2022
  2901 00005323 09C0                <1> 	or	eax, eax
  2902                              <1> 	;or 	ax, ax
  2903 00005325 7433                <1> 	jz	short itrunc_5
  2904                              <1> 		; beq 5f
  2905 00005327 56                  <1> 	push	esi
  2906                              <1> 		; mov r2,-(sp)
  2907                              <1> 	; 03/02/2022
  2908 00005328 F605[596D0000]10    <1> 	test	byte [i.flgs+1], 10h
  2909                              <1> 	;test	word [i.flgs], 1000h
  2910                              <1> 		; bit $10000,i.flgs / test large file bit?
  2911 0000532F 7423                <1> 	jz	short itrunc_4
  2912                              <1> 		; beq 4f / if clear, branch
  2913 00005331 50                  <1> 	push	eax
  2914                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2915 00005332 E8830A0000          <1> 	call	dskrd
  2916                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2917                              <1> 			     ; / pointed to by r5
  2918                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2919                              <1> 	; 03/02/2022
  2920 00005337 31C9                <1> 	xor	ecx, ecx
  2921 00005339 FEC5                <1> 	inc	ch ; mov ch, 1
  2922                              <1> 	; ecx = 256
  2923                              <1> 	;mov	ecx, 256
  2924                              <1> 		; mov $256.,r3 / move word count into r3
  2925 0000533B 89DE                <1> 	mov	esi, ebx
  2926                              <1> itrunc_2: ; 2:
  2927 0000533D 66AD                <1> 	lodsw
  2928                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2929                              <1> 			     ; / physical block number
  2930                              <1> 	; 03/02/2022
  2931 0000533F 21C0                <1> 	and	eax, eax
  2932                              <1> 	;and	ax, ax
  2933 00005341 7407                <1> 	jz	short itrunc_3
  2934                              <1> 		; beq 3f / branch if zero
  2935                              <1> 	; 03/02/2022
  2936 00005343 51                  <1> 	push	ecx
  2937                              <1> 	;push	cx
  2938                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  2939                              <1> 	;push	esi
  2940                              <1> 		; mov r5,-(sp)
  2941 00005344 E855FEFFFF          <1> 	call	free
  2942                              <1> 		; jsr r0,free / free block in free storage map
  2943                              <1> 	;pop	esi
  2944                              <1> 		; mov(sp)+,r5
  2945                              <1> 	;pop	cx
  2946 00005349 59                  <1> 	pop	ecx
  2947                              <1> 		; mov (sp)+,r3
  2948                              <1> itrunc_3: ; 3:
  2949 0000534A E2F1                <1> 	loop	itrunc_2
  2950                              <1> 		; dec r3 / decrement word count
  2951                              <1> 		; bgt 2b / branch if positive
  2952 0000534C 58                  <1> 	pop	eax
  2953                              <1> 		; mov (sp)+,r1 / put physical block number of 
  2954                              <1> 			     ; / indirect block
  2955                              <1> 	; 01/08/2013
  2956                              <1>         ;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2957                              <1> 	; 03/02/2022
  2958 0000534D 8025[596D0000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  2959                              <1> itrunc_4: ; 4:
  2960 00005354 E845FEFFFF          <1> 	call	free
  2961                              <1> 		; jsr r0,free / free indirect block
  2962 00005359 5E                  <1> 	pop	esi
  2963                              <1> 		; mov (sp)+,r2
  2964                              <1> itrunc_5: ; 5:
  2965 0000535A 81FE[6E6D0000]      <1> 	cmp	esi, i.dskp+16
  2966                              <1> 		; cmp r2,$i.dskp+16.
  2967 00005360 72BF                <1> 	jb	short itrunc_1	
  2968                              <1> 		; bne 1b / branch until all i.dskp entries check
  2969                              <1> 	; 03/02/2022
  2970                              <1> 	;and	byte [i.flgs+1], 0EFh
  2971                              <1> 	; 01/08/2013
  2972                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2973                              <1> 		; bic $10000,i.flgs / clear large file bit
  2974 00005362 BF[5E6D0000]        <1> 	mov	edi, i.dskp
  2975                              <1> 	;mov	cx, 8
  2976                              <1> 	;xor 	ax, ax
  2977                              <1> 	; 03/02/2022
  2978 00005367 29C9                <1> 	sub	ecx, ecx
  2979 00005369 B108                <1> 	mov	cl, 8
  2980 0000536B 29C0                <1> 	sub	eax, eax
  2981 0000536D 66A3[5C6D0000]      <1> 	mov	[i.size], ax ; 0
  2982                              <1> 		; clr i.size / zero file size
  2983 00005373 F366AB              <1> 	rep	stosw
  2984                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  2985                              <1> 			   ; / zero block pointers
  2986 00005376 E878FFFFFF          <1> 	call	setimod
  2987                              <1> 		; jsr r0,setimod / set i-node modified flag
  2988 0000537B 66A1[3C700000]      <1> 	mov	ax, [ii]
  2989                              <1> 		; mov ii,r1
  2990 00005381 C3                  <1> 	retn
  2991                              <1> 		; rts r0
  2992                              <1> 
  2993                              <1> imap:
  2994                              <1> 	; 12/02/2022
  2995                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2996                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  2997                              <1> 	;
  2998                              <1> 	; 'imap' finds the byte in core (superblock) containing
  2999                              <1> 	; allocation bit for an i-node whose number in r1.
  3000                              <1> 	;
  3001                              <1> 	; INPUTS ->
  3002                              <1> 	;    r1 - contains an i-number
  3003                              <1> 	;    fsp - start of table containing open files
  3004                              <1> 	;
  3005                              <1> 	; OUTPUTS ->
  3006                              <1> 	;    r2 - byte address of byte with the allocation bit
  3007                              <1> 	;    mq - a mask to locate the bit position.	
  3008                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3009                              <1> 	;
  3010                              <1> 	; ((AX = R1)) input/output
  3011                              <1> 	; ((DL/DX = MQ)) output
  3012                              <1> 	; ((BX = R2)) output
  3013                              <1> 	;
  3014                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3015                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3016                              <1> 	;
  3017                              <1> 		; / get the byte that has the allocation bit for 
  3018                              <1> 		; / the i-number contained in r1
  3019                              <1> 	;mov	dx, 1
  3020 00005382 B201                <1> 	mov	dl, 1
  3021                              <1> 		; mov $1,mq / put 1 in the mq
  3022 00005384 0FB7D8              <1> 	movzx	ebx, ax
  3023                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3024                              <1>  		          ; / in the map we must find
  3025 00005387 6683EB29            <1> 	sub	bx, 41
  3026                              <1> 		; sub $41.,r2 / r2 has i-41
  3027 0000538B 88D9                <1> 	mov	cl, bl
  3028                              <1> 		; mov r2,r3 / r3 has i-41
  3029 0000538D 80E107              <1> 	and	cl, 7
  3030                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3031                              <1> 			   ; / the bit position
  3032 00005390 7402                <1> 	jz	short imap1
  3033                              <1> 	;shl	dx, cl
  3034 00005392 D2E2                <1> 	shl	dl, cl
  3035                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3036                              <1> imap1:			   ; / to the left to mask the correct bit
  3037                              <1> 	; 03/02/2022
  3038 00005394 C1EB03              <1> 	shr	ebx, 3
  3039                              <1> 	;shr	bx, 3
  3040                              <1> 		; asr r2
  3041                              <1> 		; asr r2
  3042                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3043                              <1> 		       ; / from the start of the map
  3044                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3045 00005397 BE[147D0000]        <1> 	mov	esi, systm
  3046                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3047                              <1> 				; / the super block for drum
  3048                              <1> 	;cmp	word [cdev], 0
  3049 0000539C 803D[40700000]00    <1> 	cmp	byte [cdev], 0
  3050                              <1> 		; tst cdev / is the device the disk
  3051 000053A3 7606                <1> 	jna	short imap2
  3052                              <1> 		; beq 1f / yes
  3053 000053A5 81C608020000        <1> 	add	esi, mount - systm
  3054                              <1> 		; add $mount-systm,r2 / for mounted device,
  3055                              <1> 			; / r2 points to 1st word of its super block
  3056                              <1> imap2: ; 1:
  3057 000053AB 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3058                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3059 000053AE 6683C304            <1> 	add	bx, 4
  3060 000053B2 01F3                <1> 	add	ebx, esi
  3061                              <1>         	; add (sp)+,r2 / ?
  3062                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3063                              <1> 		      ;; (2 + free map size + 2)
  3064                              <1> 		; add $2,r2 / ?
  3065                              <1>  	
  3066                              <1> 	; 12/02/2022
  3067 000053B4 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3068 000053BA 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3069                              <1> 			  ; if inode num overs inode count
  3070                              <1> 
  3071                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3072                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3073                              <1> 
  3074                              <1> 	; 11/02/2022
  3075                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3076                              <1> 	;	(number of requested inode > inode count)
  3077                              <1> 
  3078 000053BC C3                  <1> 	retn
  3079                              <1> 		; rts r0
  2053                                  %include 'u6.s'        ; 31/05/2015
  2054                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYS6.INC
  2055                              <1> ; Last Modification: 13/06/2022
  2056                              <1> ; ----------------------------------------------------------------------------
  2057                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2058                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2059                              <1> ;
  2060                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2061                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2062                              <1> ; <Bell Laboratories (17/3/1972)>
  2063                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2064                              <1> ;
  2065                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2066                              <1> ;
  2067                              <1> ; ****************************************************************************
  2068                              <1> ; 18/11/2015
  2069                              <1> 
  2070                              <1> readi:
  2071                              <1> 	; 03/02/2022
  2072                              <1> 	; 20/05/2015
  2073                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2074                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2075                              <1> 	;
  2076                              <1> 	; Reads from an inode whose number in R1
  2077                              <1> 	; 
  2078                              <1> 	; INPUTS ->
  2079                              <1> 	;    r1 - inode number
  2080                              <1> 	;    u.count - byte count user desires
  2081                              <1> 	;    u.base - points to user buffer
  2082                              <1> 	;    u.fofp - points to word with current file offset
  2083                              <1> 	; OUTPUTS ->
  2084                              <1> 	;    u.count - cleared
  2085                              <1> 	;    u.nread - accumulates total bytes passed back
  2086                              <1> 	;
  2087                              <1> 	; ((AX = R1)) input/output
  2088                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2089                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2090                              <1> 
  2091 000053BD 31D2                <1> 	xor	edx, edx ; 0
  2092 000053BF 8915[84700000]      <1> 	mov 	[u.nread], edx ; 0
  2093                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2094 000053C5 668915[BB700000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2095 000053CC 3915[80700000]      <1> 	cmp 	[u.count], edx ; 0
  2096                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2097 000053D2 7701                <1> 	ja 	short readi_1 ; 1f
  2098                              <1> 		 ; bgt 1f / yes, branch
  2099 000053D4 C3                  <1> 	retn
  2100                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2101                              <1> readi_1: ; 1:
  2102                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2103 000053D5 6683F828            <1> 	cmp	ax, 40
  2104                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2105                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2106                              <1>         ;ja	dskr 
  2107                              <1> 		 ; ble 1f / yes, branch
  2108                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2109                              <1> 		 ;         / read file with i-node number (r1)
  2110                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2111                              <1> 	; 03/02/2022
  2112 000053D9 7605                <1> 	jna	short readi_3
  2113 000053DB E9CF000000          <1> 	jmp	dskr
  2114                              <1> readi_3:
  2115                              <1> 	; (20/05/2015)
  2116 000053E0 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2117                              <1> 	; 1:
  2118 000053E1 0FB6D8              <1> 	movzx	ebx, al
  2119                              <1> 	; 03/02/2022
  2120 000053E4 C1E302              <1> 	shl	ebx, 2
  2121                              <1> 	;shl	bx, 2
  2122                              <1> 		 ; asl r1 / multiply inode number by 2
  2123 000053E7 81C3[EB530000]      <1> 	add	ebx, readi_2 - 4
  2124 000053ED FF23                <1> 	jmp	dword [ebx]	
  2125                              <1> 		 ; jmp *1f-2(r1)
  2126                              <1> readi_2: ; 1:
  2127 000053EF [3B540000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2128                              <1> 		 ;rtty / tty; r1=2
  2129                              <1> 		 ;rppt / ppt; r1=4
  2130 000053F3 [8B540000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2131                              <1> 		 ;rmem / mem; r1=6
  2132                              <1> 		 ;rrf0 / rf0
  2133                              <1> 		 ;rrk0 / rk0
  2134                              <1> 		 ;rtap / tap0
  2135                              <1> 		 ;rtap / tap1
  2136                              <1> 		 ;rtap / tap2
  2137                              <1> 		 ;rtap / tap3
  2138                              <1> 		 ;rtap / tap4
  2139                              <1> 		 ;rtap / tap5
  2140                              <1> 		 ;rtap / tap6
  2141                              <1> 		 ;rtap / tap7
  2142 000053F7 [6B5C0000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2143 000053FB [6B5C0000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2144 000053FF [6B5C0000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2145 00005403 [6B5C0000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2146 00005407 [6B5C0000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2147 0000540B [6B5C0000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2148 0000540F [A0540000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2149 00005413 [87540000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2150                              <1> 		 ;rcvt / tty0
  2151 00005417 [87540000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2152                              <1> 		 ;rcvt / tty1
  2153 0000541B [87540000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2154                              <1> 		 ;rcvt / tty2
  2155 0000541F [87540000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2156                              <1> 		 ;rcvt / tty3
  2157 00005423 [87540000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2158                              <1> 		 ;rcvt / tty4
  2159 00005427 [87540000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2160                              <1> 		 ;rcvt / tty5
  2161 0000542B [87540000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2162                              <1> 		 ;rcvt / tty6
  2163 0000542F [87540000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2164                              <1> 		 ;rcvt / tty7
  2165 00005433 [87540000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2166                              <1> 		 ;rcrd / crd
  2167 00005437 [87540000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2168                              <1> 
  2169                              <1> rtty: ; / read from console tty
  2170                              <1> 	; 03/02/2022
  2171                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2172                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2173                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2174                              <1> 	;	     must be written immediate on video page (screen)
  2175                              <1> 	;	     when it is required.	
  2176                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2177                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2178                              <1> 	;
  2179                              <1> 	; Console tty buffer is PC keyboard buffer
  2180                              <1> 	; and keyboard-keystroke handling is different than original
  2181                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2182                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2183                              <1> 	;
  2184                              <1> 	; 06/12/2013
  2185 0000543B 0FB61D[A5700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2186 00005442 8A83[B76D0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2187                              <1> rttys:
  2188                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2189                              <1> 	               ; / of the control and status block
  2190                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2191                              <1> 		       ; / tty buffer
  2192                              <1> 	; 28/07/2013
  2193 00005448 A2[AA700000]        <1> 	mov 	[u.ttyn], al
  2194                              <1> 	; 13/01/2014
  2195 0000544D FEC0                <1> 	inc	al
  2196 0000544F A2[8C700000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2197                              <1> rtty_nc: ; 01/02/2014
  2198                              <1> 	; 29/09/2013
  2199                              <1> 	;mov	ecx, 10
  2200                              <1> 	; 03/02/2022
  2201 00005454 29C9                <1> 	sub	ecx, ecx
  2202 00005456 B10A                <1> 	mov	cl, 10
  2203                              <1> rtty_1: 	; 01/02/2014
  2204                              <1> 	;push 	cx ; 29/09/2013
  2205                              <1> 	; 03/02/2022
  2206 00005458 51                  <1> 	push	ecx
  2207                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2208 00005459 B001                <1> 	mov 	al, 1
  2209 0000545B E85B0C0000          <1> 	call 	getc
  2210                              <1> 	; 03/02/2022
  2211 00005460 59                  <1> 	pop	ecx
  2212                              <1> 	;pop 	cx ; 29/09/2013	
  2213 00005461 7516                <1> 	jnz	short rtty_2
  2214                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2215                              <1> 	               ; / of chars. Is this number non-zero?
  2216 00005463 E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2217                              <1> 	; 05/10/2013
  2218 00005465 8A25[AA700000]      <1> 	mov	ah, [u.ttyn]
  2219                              <1> 	; 29/09/2013
  2220 0000546B E898FBFFFF          <1> 	call	sleep
  2221                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2222                              <1>                 ;           / (120 chars.)
  2223                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2224 00005470 EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2225                              <1> 
  2226                              <1> rtty_idle:
  2227                              <1> 	; 29/07/2013
  2228 00005472 E804FBFFFF          <1> 	call 	idle
  2229 00005477 EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2230                              <1> 	;1:
  2231                              <1> 		; tst 2(r5) / is the number of characters zero
  2232                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2233                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2234                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2235                              <1> 		          ; / contains the next char.
  2236                              <1> 		; dec 2(r5) / decrement the character count
  2237                              <1> rtty_2:
  2238 00005479 30C0                <1> 	xor 	al, al
  2239 0000547B E83B0C0000          <1> 	call 	getc
  2240 00005480 E892000000          <1> 	call	passc
  2241                              <1> 		; jsr r0,passc / move the character to core (user)
  2242                              <1> 	;; 17/10/2015 - 16/07/2015
  2243                              <1> 	; 19/06/2014
  2244                              <1> 	;;jnz	short rtty_nc
  2245 00005485 58                  <1> 	pop	eax  ; (20/05/2015)
  2246 00005486 C3                  <1> 	retn 
  2247                              <1> ;ret1:
  2248                              <1> 		; jmp ret / return to caller via 'ret'
  2249                              <1> 
  2250                              <1> rcvt:   ; < receive/read character from tty >
  2251                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2252                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2253                              <1> 	;
  2254                              <1> 	; Retro UNIX 8086 v1 modification !
  2255                              <1> 	; 
  2256                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2257                              <1> 	;		(exactly different than this one)
  2258                              <1> 	;	was in 'u9.s' file.
  2259                              <1> 	;
  2260 00005487 2C0A                <1> 	sub 	al, 10
  2261                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2262                              <1> 	; 16/07/2013
  2263                              <1> 	; 21/05/2013
  2264 00005489 EBBD                <1>         jmp     short rttys
  2265                              <1>       
  2266                              <1> ;rppt: / read paper tape
  2267                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2268                              <1> ;			 / places
  2269                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2270                              <1> ;		       / also enables read bit in prs
  2271                              <1> ;	jsr	r0,passc / place character in users buffer area
  2272                              <1> ;	br	rppt
  2273                              <1> 
  2274                              <1> rmem: ; / transfer characters from memory to a user area of core
  2275                              <1> 	; 17/10/2015
  2276                              <1> 	; 11/06/2015
  2277                              <1> 	; 24/05/2015
  2278                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2279                              <1> 	;
  2280 0000548B 8B35[6C700000]      <1> 	mov     esi, [u.fofp]
  2281                              <1> rmem_1:
  2282 00005491 8B1E                <1>         mov     ebx, [esi]        
  2283                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2284                              <1> 		               ; / to be transferred to user
  2285 00005493 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2286                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2287                              <1> 			    ; / char in memory file
  2288 00005495 8A03                <1> 	mov	al, [ebx]
  2289                              <1> 		; movb (r1),r1 / get character from memory file, 
  2290                              <1> 		             ; / put it in r1
  2291 00005497 E87B000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2292                              <1> 			     ;  / the next byte of the users core area
  2293                              <1> 		; br rmem / continue
  2294 0000549C 75F3                <1> 	jnz	short rmem_1
  2295                              <1> ret_:
  2296 0000549E 58                  <1> 	pop	eax ; 09/06/2015
  2297 0000549F C3                  <1> 	retn
  2298                              <1> 
  2299                              <1> rlpr:
  2300                              <1> ;1:
  2301                              <1> ;rcrd:
  2302 000054A0 C705[AB700000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2302 000054A8 0000                <1>
  2303 000054AA E924E6FFFF          <1> 	jmp	error
  2304                              <1> 		;jmp	error / see 'error' routine
  2305                              <1> 
  2306                              <1> dskr:
  2307                              <1> 	; 12/10/2015
  2308                              <1> 	; 21/08/2015
  2309                              <1> 	; 25/07/2015
  2310                              <1> 	; 10/07/2015
  2311                              <1> 	; 16/06/2015
  2312                              <1> 	; 31/05/2015
  2313                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2314                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2315                              <1> dskr_0:
  2316 000054AF 50                  <1> 	push	eax
  2317                              <1> 		; mov (sp),r1 / i-number in r1
  2318                              <1> 	; AX = i-number
  2319 000054B0 E834FDFFFF          <1> 	call	iget
  2320                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2321 000054B5 0FB715[5C6D0000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2322                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2323 000054BC 8B1D[6C700000]      <1> 	mov	ebx, [u.fofp]
  2324 000054C2 2B13                <1> 	sub	edx, [ebx]
  2325                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2326                              <1>         ; 12/10/2015
  2327                              <1> 	; jna     short ret_ 
  2328                              <1> 		; blos ret
  2329 000054C4 7709                <1> 	ja	short dskr_1
  2330                              <1> 	;
  2331                              <1> dskr_retn: ; 12/10/2015
  2332 000054C6 58                  <1> 	pop	eax
  2333 000054C7 C605[BD700000]00    <1> 	mov	byte [u.kcall], 0
  2334 000054CE C3                  <1> 	retn	
  2335                              <1> dskr_1: 
  2336 000054CF 3B15[80700000]      <1> 	cmp     edx, [u.count] 
  2337                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2338                              <1> 			       ; / to carry out read
  2339 000054D5 7306                <1> 	jnb	short dskr_2
  2340                              <1> 		; bhis 1f
  2341 000054D7 8915[80700000]      <1> 	mov	[u.count], edx
  2342                              <1> 		; mov r2,u.count / no, just read to end of file
  2343                              <1> dskr_2: ; 1:
  2344                              <1> 	; AX = i-number
  2345 000054DD E89EFBFFFF          <1> 	call	mget
  2346                              <1> 		; jsr r0,mget / returns physical block number of block 
  2347                              <1> 			    ; / in file where offset points
  2348                              <1> 	; eAX = physical block number
  2349 000054E2 E8D3080000          <1> 	call	dskrd
  2350                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2351                              <1> 			     ; / 1st word of data in buffer
  2352                              <1> 	; 09/06/2015
  2353 000054E7 803D[BD700000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2354 000054EE 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2355 000054F0 66833D[BB700000]00  <1> 	cmp	word [u.pcount], 0
  2356 000054F8 7705                <1> 	ja	short dskr_4
  2357                              <1> dskr_3:
  2358                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2359 000054FA E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2360                              <1> dskr_4:
  2361                              <1> 	; eBX (r5) = system (I/O) buffer address -physical-
  2362 000054FF E831030000          <1> 	call	sioreg
  2363                              <1> 		; jsr r0,sioreg
  2364 00005504 87F7                <1> 	xchg	esi, edi
  2365                              <1> 	; eDI = file (user data) offset
  2366                              <1> 	; eSI = sector (I/O) buffer offset
  2367                              <1> 	; eCX = byte count
  2368 00005506 F3A4                <1> 	rep	movsb
  2369                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2370                              <1> 		                 ; / starting at u.base
  2371                              <1> 		; dec r3
  2372                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2373                              <1> 	; 25/07/2015
  2374                              <1> 	; eax = remain bytes in buffer
  2375                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2376 00005508 09C0                <1> 	or	eax, eax
  2377 0000550A 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2378                              <1> 	; 03/08/2013
  2379                              <1> 	;pop	eax
  2380 0000550C 390D[80700000]      <1> 	cmp	[u.count], ecx ; 0
  2381                              <1> 		; tst u.count / all bytes read off disk
  2382                              <1> 		; bne dskr
  2383                              <1> 		; br ret
  2384                              <1>         ;ja      short dskr_0
  2385                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2386                              <1> 	;retn
  2387                              <1> 	; 12/10/2015
  2388 00005512 76B2                <1> 	jna	short dskr_retn
  2389 00005514 58                  <1> 	pop	eax  ; (i-node number)
  2390 00005515 EB98                <1> 	jmp	short dskr_0
  2391                              <1> 	
  2392                              <1> passc:
  2393                              <1> 	; 18/10/2015
  2394                              <1> 	; 10/07/2015
  2395                              <1> 	; 01/07/2015
  2396                              <1> 	; 08/06/2015
  2397                              <1> 	; 04/06/2015
  2398                              <1> 	; 20/05/2015
  2399                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2400                              <1> 	;
  2401                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2402                              <1> 	;		      to physical address
  2403 00005517 66833D[BB700000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2404                              <1> 			     ; 1-4095 --> use previous physical base address
  2405                              <1> 			     ; in [u.pbase]
  2406 0000551F 7705                <1> 	ja	short passc_3
  2407                              <1> 	; 08/06/2015 - 10/07/2015
  2408 00005521 E82C000000          <1> 	call	trans_addr_w
  2409                              <1> passc_3:
  2410                              <1> 	; 19/05/2015
  2411 00005526 66FF0D[BB700000]    <1> 	dec	word [u.pcount]
  2412                              <1> 	;
  2413 0000552D 8B1D[B7700000]      <1> 	mov	ebx, [u.pbase]
  2414 00005533 8803                <1> 	mov	[ebx], al
  2415                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2416                              <1> 		               ; / users buffer
  2417 00005535 FF05[7C700000]      <1> 	inc	dword [u.base]
  2418                              <1> 		; inc u.base / increment the pointer to point to 
  2419                              <1> 			  ; / the next byte in users buffer
  2420 0000553B FF05[B7700000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2421 00005541 FF05[84700000]      <1> 	inc	dword [u.nread]
  2422                              <1> 		; inc u.nread / increment the number of bytes read
  2423 00005547 FF0D[80700000]      <1> 	dec	dword [u.count]
  2424                              <1> 		; dec u.count / decrement the number of bytes to be read
  2425                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2426 0000554D C3                  <1> 	retn
  2427                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2428                              <1> 		             ; / 'readi' by:
  2429                              <1> 		;/ (1) pop the return address off the stack into r0
  2430                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2431                              <1> 	;1:
  2432                              <1> 		; clr	*$ps / clear processor status
  2433                              <1> 		; rts r0 / return to address currently on top of stack
  2434                              <1> 
  2435                              <1> trans_addr_r:
  2436                              <1> 	; Translate virtual address to physical address 
  2437                              <1> 	; for reading from user's memory space
  2438                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2439                              <1> 	; 18/10/2015
  2440                              <1> 	; 10/07/2015
  2441                              <1> 	; 09/06/2015
  2442                              <1> 	; 08/06/2015 
  2443                              <1> 	; 04/06/2015
  2444                              <1> 	;
  2445                              <1> 	; 18/10/2015
  2446 0000554E 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2447 00005550 EB04                <1> 	jmp 	short trans_addr_rw
  2448                              <1> 
  2449                              <1> 	;push	eax
  2450                              <1> 	;push	ebx
  2451                              <1> 	;mov	ebx, [u.base]
  2452                              <1> 	;call	get_physical_addr ; get physical address
  2453                              <1> 	;;jnc	short cpass_0
  2454                              <1> 	;jnc	short passc_1
  2455                              <1> 	;mov	[u.error], eax
  2456                              <1> 	;;pop	ebx
  2457                              <1> 	;;pop	eax
  2458                              <1> 	;jmp	error
  2459                              <1> ;cpass_0:
  2460                              <1> 	; 18/10/2015
  2461                              <1> 	; 20/05/2015
  2462                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2463                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2464                              <1> 	;pop	ebx
  2465                              <1> 	;pop	eax
  2466                              <1> 	;retn	; 08/06/2015
  2467                              <1> 
  2468                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2469                              <1> trans_addr_w:
  2470                              <1> 	; Translate virtual address to physical address 
  2471                              <1> 	; for writing to user's memory space
  2472                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2473                              <1> 	; 18/10/2015
  2474                              <1> 	; 29/07/2015
  2475                              <1> 	; 10/07/2015
  2476                              <1> 	; 09/06/2015
  2477                              <1> 	; 08/06/2015
  2478                              <1> 	; 04/06/2015 (passc)
  2479                              <1> 	;
  2480                              <1> 	; 18/10/2015
  2481 00005552 29D2                <1> 	sub	edx, edx
  2482 00005554 FEC2                <1> 	inc	dl ; 1 (write access sign)
  2483                              <1> trans_addr_rw:
  2484 00005556 50                  <1> 	push	eax
  2485 00005557 53                  <1> 	push	ebx
  2486                              <1> 	; 18/10/2015
  2487 00005558 52                  <1> 	push 	edx ; r/w sign (in DL)
  2488                              <1> 	;
  2489 00005559 8B1D[7C700000]      <1> 	mov	ebx, [u.base]
  2490 0000555F E854DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2491 00005564 730A                <1> 	jnc	short passc_0
  2492 00005566 A3[AB700000]        <1> 	mov	[u.error], eax
  2493                              <1> 	;pop	edx
  2494                              <1> 	;pop 	ebx
  2495                              <1> 	;pop	eax
  2496 0000556B E963E5FFFF          <1> 	jmp	error
  2497                              <1> passc_0:
  2498 00005570 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2499 00005573 5A                  <1> 	pop	edx ; 18/10/2015
  2500 00005574 7517                <1> 	jnz	short passc_1
  2501                              <1> 	; 18/10/2015
  2502 00005576 20D2                <1> 	and 	dl, dl
  2503 00005578 7413                <1> 	jz	short passc_1
  2504                              <1> 	; 20/05/2015
  2505                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2506                              <1> 	; EBX = linear address
  2507 0000557A 51                  <1> 	push 	ecx
  2508 0000557B 53                  <1> 	push	ebx ; * ; 03/02/2022 (BugFix)
  2509 0000557C E8A6DBFFFF          <1> 	call 	copy_page
  2510 00005581 5B                  <1> 	pop	ebx ; * ; 03/02/2022 (BugFix)
  2511 00005582 59                  <1> 	pop	ecx
  2512 00005583 7217                <1> 	jc	short passc_2
  2513                              <1> 	; 03/02/2022
  2514                              <1> 	;push	eax ; physical address of the new/allocated page
  2515                              <1> 	;call	add_to_swap_queue
  2516                              <1> 	;pop	eax
  2517                              <1> 	; 18/10/2015
  2518 00005585 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2519                              <1> 	;mov 	ecx, PAGE_SIZE
  2520                              <1> 	;sub	ecx, ebx 
  2521 0000558B 01D8                <1> 	add	eax, ebx  
  2522                              <1> passc_1: 
  2523                              <1> 	; 18/10/2015
  2524                              <1> 	; 20/05/2015
  2525 0000558D A3[B7700000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2526 00005592 66890D[BB700000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2527 00005599 5B                  <1> 	pop	ebx
  2528 0000559A 58                  <1> 	pop	eax
  2529 0000559B C3                  <1> 	retn	; 08/06/2015
  2530                              <1> passc_2:
  2531 0000559C C705[AB700000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2531 000055A4 0000                <1>
  2532                              <1> 	;pop 	ebx
  2533                              <1> 	;pop	eax
  2534 000055A6 E928E5FFFF          <1> 	jmp	error
  2535                              <1> 
  2536                              <1> writei:
  2537                              <1> 	; 13/06/2022
  2538                              <1> 	; 03/02/2022
  2539                              <1> 	; 20/05/2015
  2540                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2541                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2542                              <1> 	;
  2543                              <1> 	; Write data to file with inode number in R1
  2544                              <1> 	; 
  2545                              <1> 	; INPUTS ->
  2546                              <1> 	;    r1 - inode number
  2547                              <1> 	;    u.count - byte count to be written
  2548                              <1> 	;    u.base - points to user buffer
  2549                              <1> 	;    u.fofp - points to word with current file offset
  2550                              <1> 	; OUTPUTS ->
  2551                              <1> 	;    u.count - cleared
  2552                              <1> 	;    u.nread - accumulates total bytes passed back	
  2553                              <1> 	; ((AX = R1))
  2554                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2555                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2556                              <1> 
  2557 000055AB 31C9                <1> 	xor	ecx, ecx
  2558 000055AD 890D[84700000]      <1> 	mov 	[u.nread], ecx  ; 0
  2559                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2560                              <1> 		            ; / read or write calls
  2561 000055B3 66890D[BB700000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2562 000055BA 390D[80700000]      <1> 	cmp 	[u.count], ecx
  2563                              <1> 	;	; tst u.count / test the byte count specified by the user
  2564 000055C0 770B                <1> 	ja 	short writei_1 ; 1f
  2565                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2566                              <1> 
  2567                              <1> 	; 13/06/2022 - ('get/read LPT printer status' modification)
  2568 000055C2 83F810              <1> 	cmp	eax, 16  ; LPR_INODE ; lpt (parallel port printer) ?
  2569 000055C5 7505                <1> 	jne	short writei_0
  2570 000055C7 E924010000          <1> 	jmp	lpr_stat	; get/read line status
  2571                              <1> writei_0:
  2572 000055CC C3                  <1> 	retn
  2573                              <1> 	;	; rts r0 / no, return - no writing to do
  2574                              <1> writei_1: ;1:
  2575                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2576 000055CD 6683F828            <1> 	cmp 	ax, 40
  2577                              <1> 		; cmp r1,$40.
  2578                              <1> 		; / does the i-node number indicate a special file?
  2579                              <1> 	;ja	dskw 
  2580                              <1> 		; bgt dskw / no, branch to standard file output
  2581                              <1> 	; 03/02/2022
  2582 000055D1 7605                <1> 	jna	short writei_3
  2583 000055D3 E958010000          <1> 	jmp	dskw
  2584                              <1> writei_3:
  2585                              <1> 	; (20/05/2015)
  2586 000055D8 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2587 000055D9 0FB6D8              <1> 	movzx	ebx, al
  2588                              <1> 	; 03/02/2022
  2589 000055DC C1E302              <1> 	shl	ebx, 2
  2590                              <1> 	;shl	bx, 2
  2591                              <1> 		; asl r1 / yes, calculate the index into the special file
  2592 000055DF 81C3[E3550000]      <1> 	add	ebx, writei_2 - 4
  2593 000055E5 FF23                <1> 	jmp	dword [ebx]	
  2594                              <1> 		; jmp *1f-2(r1)
  2595                              <1> 		; / jump table and jump to the appropriate routine
  2596                              <1> writei_2: ;1:
  2597 000055E7 [33560000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2598                              <1> 		 ;wtty / tty; r1=2
  2599                              <1> 		 ;wppt / ppt; r1=4
  2600 000055EB [86560000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2601                              <1> 		 ;wmem / mem; r1=6
  2602                              <1> 		 ;wrf0 / rf0
  2603                              <1> 		 ;wrk0 / rk0
  2604                              <1> 		 ;wtap / tap0
  2605                              <1> 		 ;wtap / tap1
  2606                              <1> 		 ;wtap / tap2
  2607                              <1> 		 ;wtap / tap3
  2608                              <1> 		 ;wtap / tap4
  2609                              <1> 		 ;wtap / tap5
  2610                              <1> 		 ;wtap / tap6
  2611                              <1> 		 ;wtap / tap7
  2612 000055EF [F45C0000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2613 000055F3 [F45C0000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2614 000055F7 [F45C0000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2615 000055FB [F45C0000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2616 000055FF [F45C0000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2617 00005603 [F45C0000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2618 00005607 [B6560000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2619 0000560B [80560000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2620                              <1> 		 ;xmtt / tty0
  2621 0000560F [80560000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2622                              <1> 		 ;xmtt / tty1
  2623 00005613 [80560000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2624                              <1> 		 ;xmtt / tty2
  2625 00005617 [80560000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2626                              <1> 		 ;xmtt / tty3
  2627 0000561B [80560000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2628                              <1> 		 ;xmtt / tty4
  2629 0000561F [80560000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2630                              <1> 		 ;xmtt / tty5
  2631 00005623 [80560000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2632                              <1> 		 ;xmtt / tty6
  2633 00005627 [80560000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2634                              <1> 		 ;xmtt / tty7
  2635 0000562B [80560000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2636                              <1> 		; / wlpr / lpr
  2637 0000562F [80560000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2638                              <1> 
  2639                              <1> wtty: ; write to console tty (write to screen)
  2640                              <1> 	; 03/02/2022
  2641                              <1> 	; 18/11/2015
  2642                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2643                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2644                              <1> 	;
  2645                              <1> 	; Console tty output is on current video page
  2646                              <1> 	; Console tty character output procedure is changed here
  2647                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2648                              <1> 	;
  2649 00005633 0FB61D[A5700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2650 0000563A 8AA3[B76D0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2651 00005640 88E0                <1> 	mov	al, ah ; 07/07/2014
  2652                              <1> wttys:	
  2653                              <1> 	; 10/10/2013
  2654 00005642 8825[AA700000]      <1> 	mov 	[u.ttyn], ah
  2655                              <1> 	; 13/01/2014
  2656 00005648 FEC0                <1> 	inc	al
  2657 0000564A A2[8D700000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2658                              <1> wtty_nc: ; 15/05/2013
  2659                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2660 0000564F E881010000          <1> 	call	cpass
  2661                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2662                              <1> 		             ; / none go to return address in syswrite
  2663                              <1> 		; tst r1 / is character = null
  2664                              <1> 		; beq wtty / yes, get next character
  2665                              <1> 	; 10/10/2013
  2666 00005654 7428                <1> 	jz	short wret
  2667                              <1> 	;1 :
  2668                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2669                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2670                              <1> 		;	          / than 20
  2671                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2672                              <1> 	; 27/06/2014
  2673                              <1> wtty_1:
  2674                              <1> 	; AH = tty number
  2675                              <1> 	; AL = ASCII code of the character
  2676                              <1> 	; 15/04/2014
  2677                              <1> 	;push	ax
  2678                              <1> 	; 03/02/2022
  2679 00005656 50                  <1> 	push	eax
  2680 00005657 E8CD0A0000          <1> 	call	putc ; 14/05/2013
  2681 0000565C 731D                <1> 	jnc	short wtty_2
  2682                              <1> 	; 18/11/2015
  2683 0000565E E818F9FFFF          <1> 	call	idle
  2684                              <1> 	;mov	ax, [esp]
  2685                              <1> 	; 03/02/2022
  2686 00005663 8B0424              <1> 	mov	eax, [esp]
  2687 00005666 E8BE0A0000          <1> 	call	putc
  2688 0000566B 730E                <1> 	jnc	short wtty_2 
  2689                              <1> 	; 02/06/2014
  2690 0000566D 8A25[AA700000]      <1> 	mov	ah, [u.ttyn]
  2691 00005673 E890F9FFFF          <1> 	call	sleep
  2692                              <1> 	; 03/02/2022
  2693 00005678 58                  <1> 	pop	eax
  2694                              <1> 	;pop	ax
  2695 00005679 EBDB                <1> 	jmp 	short wtty_1
  2696                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2697                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2698                              <1> 			      ; / console tty and
  2699                              <1> 		; br 	2f / place character in list; if none available
  2700                              <1> 		   	  ; / branch to put process to sleep
  2701                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2702                              <1> wtty_2:
  2703                              <1> 	; 15/04/2014
  2704                              <1> 	;pop	ax
  2705                              <1> 	; 03/02/2022
  2706 0000567B 58                  <1> 	pop	eax
  2707 0000567C EBD1                <1> 	jmp	short wtty_nc
  2708                              <1> 		; br wtty
  2709                              <1> wret:	; 10/10/2013 (20/05/2015)
  2710 0000567E 58                  <1> 	pop	eax
  2711 0000567F C3                  <1> 	retn
  2712                              <1> 	;2:
  2713                              <1> 		;mov	r1,-(sp) / place character on stack
  2714                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2715                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2716                              <1> 		;br	1b / try again to place character in clist and output
  2717                              <1> 
  2718                              <1> xmtt:   ; < send/write character to tty >
  2719                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2720                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2721                              <1> 	;
  2722                              <1> 	; Retro UNIX 8086 v1 modification !
  2723                              <1> 	; 
  2724                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2725                              <1> 	;		(exactly different than this one)
  2726                              <1> 	;	was in 'u9.s' file.
  2727                              <1> 	;
  2728 00005680 2C0A                <1> 	sub 	al, 10
  2729                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2730                              <1> 	; 10/10/2013
  2731 00005682 88C4                <1> 	mov	ah, al
  2732                              <1> 	; 28/07/2013
  2733 00005684 EBBC                <1> 	jmp	short wttys
  2734                              <1> 
  2735                              <1> ;wppt:
  2736                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2737                              <1> ;		         / if none return to writei's calling routine
  2738                              <1> ;	jsr	r0,pptoc / output character on ppt
  2739                              <1> ;	br	wppt
  2740                              <1> 
  2741                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2742                              <1> 	; 17/10/2015
  2743                              <1> 	; 11/06/2015
  2744                              <1> 	; 24/05/2015
  2745                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2746                              <1> 	;
  2747 00005686 813D[28070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2747 0000568C [9E4F0000]          <1>
  2748 00005690 7415                <1>         je      short wmem_acc_err
  2749                              <1> 	;
  2750 00005692 8B35[6C700000]      <1>         mov     esi, [u.fofp] 
  2751                              <1> wmem_1:
  2752 00005698 E838010000          <1> 	call	cpass
  2753                              <1> 		; jsr r0,cpass / get next character from users area of
  2754                              <1> 			     ; / core and put it in r1
  2755                              <1>         	; mov r1,-(sp) / put character on the stack
  2756                              <1> 	; 20/09/2013
  2757 0000569D 74DF                <1> 	jz	short wret ; wmem_2  
  2758 0000569F 8B1E                <1>         mov     ebx, [esi]
  2759                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2760 000056A1 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2761                              <1> 		; inc *u.fofp / increment file offset to point to next
  2762                              <1> 			    ; / available location in file
  2763 000056A3 8803                <1> 	mov	[ebx], al	
  2764                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2765                              <1> 			        ; / assigned to it
  2766 000056A5 EBF1                <1> 	jmp	short wmem_1
  2767                              <1> 		; br wmem / continue
  2768                              <1> 	;1:
  2769                              <1> 	;jmp	error / ?
  2770                              <1> ;wmem_2:	
  2771                              <1> ;	; 20/09/2013
  2772                              <1> ;	pop	ax
  2773                              <1> ;	retn
  2774                              <1> 
  2775                              <1> wmem_acc_err:
  2776 000056A7 C705[AB700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2776 000056AF 0000                <1>
  2777 000056B1 E91DE4FFFF          <1> 	jmp	error
  2778                              <1> 
  2779                              <1> ;wlpr:
  2780                              <1> 	; 13/06/2022
  2781                              <1>         ;mov	dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2782                              <1> 	;jmp	error   ; ... Printing procedure will be located here ...
  2783                              <1> 		;/	jsr	r0,cpass
  2784                              <1> 		;/	cmp	r0,$'a
  2785                              <1> 		;/	blo	1f
  2786                              <1> 		;/	cmp	r1,$'z
  2787                              <1> 		;/	bhi	1f
  2788                              <1> 		;/	sub	$40,r1
  2789                              <1> 		;/1:
  2790                              <1> 		;/	jsr	r0,lptoc
  2791                              <1> 		;/	br	wlpr
  2792                              <1> 		; br rmem / continue
  2793                              <1> 
  2794                              <1> ; 13/06/2022 - Retro UNIX 386 v1 - PRINTER BIOS (Functions)
  2795                              <1> 
  2796                              <1> ;; Ref: MSDOS 3.3 (Retro DOS 3.2) Printer driver code (MSLPT.ASM)
  2797                              <1> ;; MSLPT.ASM - MSDOS 3.3 - 24/07/1987
  2798                              <1> ;; 23/03/2018 - Retro DOS v2.0
  2799                              <1> ;; RETRODOS32.ASM - 03/08/2019 (Retro DOS v3.2)
  2800                              <1> 
  2801                              <1> ; IBM ROMBIOS (INT 17h) STATUS BITS
  2802                              <1> 
  2803                              <1> NOTBUSYSTATUS	equ 10000000b	; NOT BUSY
  2804                              <1> ACKSTATUS	equ 01000000b	; ACKNOWLEDGE (FOR WHAT?)
  2805                              <1> NOPAPERSTATUS	equ 00100000b	; NO MORE PAPER
  2806                              <1> SELECTEDSTATUS	equ 00010000b	; THE PRINTER SAID IT WAS SELECTED
  2807                              <1> IOERRSTATUS	equ 00001000b	; SOME KIND ERROR
  2808                              <1> RESERVED	equ 00000110b	; NOPS
  2809                              <1> TIMEOUTSTATUS	equ 00000001b	; TIME OUT.
  2810                              <1> 
  2811                              <1> ;----------------------------------------------------------------
  2812                              <1> ;								:
  2813                              <1> ;		WRITE TO PRINTER DEVICE 			:
  2814                              <1> ;								:
  2815                              <1> ;   CX has count of bytes to be printed 			:
  2816                              <1> ;   ES:DI point to source buffer contains characters		:
  2817                              <1> ;   AuxNum (in msbio.asm) has printer number			:
  2818                              <1> ;								:
  2819                              <1> ;----------------------------------------------------------------
  2820                              <1> 
  2821                              <1> wlpr:
  2822                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2823                              <1> PRN$WRIT:
  2824                              <1> 	; INPUT:
  2825                              <1> 	;	[u.count] = count of characters to be printed
  2826                              <1> 	;	[u.base] = buffer address in user's memory space
  2827                              <1> 	;
  2828                              <1> 	;	(if ECX = 0, printer status will be returned)
  2829                              <1> 	
  2830                              <1> 	;xor	ebx, ebx
  2831                              <1> PRN$LOOP:
  2832 000056B6 E81A010000          <1> 	call	cpass		  ; Get a character into AL
  2833 000056BB 7431                <1> 	jz	short pr_exit
  2834                              <1> 	;
  2835 000056BD B302                <1> 	mov	bl, 2  ; retry count
  2836                              <1> PRN$OUT:
  2837                              <1> 	; al = character which will be printed
  2838 000056BF 30E4                <1> 	xor	ah, ah ; 0	  ; PRINT THE CHARACTER IN (AL)
  2839 000056C1 E850000000          <1> 	call	PRNOP
  2840 000056C6 74EE                <1> 	jz	short PRN$LOOP 	  ; if error, try to print again
  2841                              <1> PrRetry:
  2842                              <1> 	; al = character
  2843 000056C8 FECB                <1> 	dec	bl
  2844 000056CA 75F3                <1> 	jnz	short PRN$OUT
  2845                              <1> pr_err_exit:
  2846 000056CC 0FB6C0              <1> 	movzx	eax, al
  2847 000056CF A3[AB700000]        <1> 	mov	[u.error], eax
  2848 000056D4 A3[5C700000]        <1> 	mov	[u.r0], eax ; error code in AL
  2849 000056D9 8B2D[54700000]      <1> 	mov 	ebp, [u.sp]
  2850                              <1> 			; Kernel stack at the beginning of sys call
  2851 000056DF 8B15[84700000]      <1> 	mov	edx, [u.nread]
  2852 000056E5 4A                  <1> 	dec	edx ; last char failed
  2853 000056E6 895514              <1> 	mov	[ebp+20], edx ; count of printed chacters in edx
  2854 000056E9 E9E5E3FFFF          <1> 	jmp	error
  2855                              <1> pr_exit:
  2856 000056EE 58                  <1> 	pop	eax ; inode number
  2857                              <1> 
  2858                              <1> 	;mov	eax, [u.nread]
  2859                              <1> 	;mov	[u.r0], eax ; count of printed chacters
  2860                              <1> 	;jmp	sysret
  2861 000056EF C3                  <1> 	retn	; return from writei to syswrite (rw0)
  2862                              <1> 
  2863                              <1> ; 13/06/2022
  2864                              <1> 
  2865                              <1> ;----------------------------------------------------------------
  2866                              <1> ;								:
  2867                              <1> ;		PRINTER STATUS ROUTINE				:
  2868                              <1> ;								:
  2869                              <1> ;----------------------------------------------------------------
  2870                              <1> ;
  2871                              <1> 
  2872                              <1> lpr_stat:
  2873                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2874                              <1> PRN$STAT:
  2875 000056F0 E81F000000          <1> 	call	PRNSTAT		  ; get the status
  2876 000056F5 750E                <1> 	jnz	short prn_stat_retn
  2877                              <1> 				  ; if error jump to error routine
  2878                              <1> 	;mov	al, 9		  ; AGAIN, ASSUME OUT OF PAPER...
  2879 000056F7 B01F                <1> 	mov	al, ERR_PRN_PAPER
  2880 000056F9 F6C420              <1> 	test	ah, NOPAPERSTATUS
  2881 000056FC 7507                <1> 	jnz	short prn_stat_retn
  2882 000056FE F6C480              <1> 	test	ah, NOTBUSYSTATUS
  2883 00005701 750D                <1> 	jnz	short prn_stat_ok ; if not busy return (with cf=0)
  2884 00005703 B022                <1> 	mov	al, ERR_PRN_BUSY  ; else busy, return to busy exit
  2885                              <1> prn_stat_retn:
  2886                              <1> 	; al = error code
  2887                              <1> 	; ah = status flags
  2888 00005705 A3[5C700000]        <1> 	mov	[u.r0], eax
  2889                              <1> 	;movzx	eax, al
  2890                              <1> 	;mov 	[u.error], eax
  2891 0000570A 58                  <1> 	pop	eax ; discard return address to syswrite
  2892 0000570B E9E3E3FFFF          <1> 	jmp	sysret
  2893                              <1> prn_stat_ok:
  2894 00005710 30C0                <1> 	xor	al, al ; 0
  2895 00005712 EBF1                <1> 	jmp	short prn_stat_retn
  2896                              <1> 
  2897                              <1> ;
  2898                              <1> ;   PRNSTAT	get printer status
  2899                              <1> ;   PRNOP	print a character
  2900                              <1> ;
  2901                              <1> ; PRNSTAT and PRNOP are two routines which call on the ROM-BIOS
  2902                              <1> ; printer routines.  The routines share code which calls on the bios and
  2903                              <1> ; then determines which, if any, error occured. PRNSTAT and PRNOP differ
  2904                              <1> ; only by the value put into AH before the ROM-BIOS call.
  2905                              <1> ;
  2906                              <1> ;   INPUT	if PRNOP then character in AL
  2907                              <1> ;
  2908                              <1> ;   OUTPUT	- AL holds error code
  2909                              <1> ;		- AH status byte from printer
  2910                              <1> ;		- flag NZ if error
  2911                              <1> 
  2912                              <1> PRNSTAT:
  2913 00005714 B402                <1> 	mov	ah, 2		  ; set command for get status 
  2914                              <1> 
  2915                              <1> PRNOP:
  2916                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2917                              <1> 	;
  2918                              <1> 	; Print character (on paper)
  2919                              <1> 
  2920                              <1> 	; INPUT:
  2921                              <1> 	;	al = character to be printed
  2922                              <1> 	; OUTPUT:
  2923                              <1> 	;	zf = 1 -> ok
  2924                              <1> 	;	zf = 0 -> error code in AL
  2925                              <1> 
  2926 00005716 E8470C0000          <1> 	call	int17h	 ; call lpt bios
  2927                              <1> 	
  2928 0000571B F6C408              <1> 	test	ah, IOERRSTATUS	  ; I/O ERROR?
  2929 0000571E 740A                <1> 	jz	short short prnop_chk_nrdy ; NO, TRY NOT READY
  2930                              <1> 
  2931                              <1> 	; AT THIS POINT, WE KNOW WE HAVE AN ERROR.
  2932                              <1> 	; THE CONVERSE IS NOT TRUE.
  2933                              <1> 
  2934                              <1> 	;mov	al, 9		  ; FIRST, ASSUME OUT OF PAPER
  2935 00005720 B01F                <1> 	mov	al, ERR_PRN_PAPER
  2936 00005722 F6C420              <1> 	test	ah, NOPAPERSTATUS ; OUT OF PAPER SET?
  2937 00005725 7502                <1> 	jnz	short PRNOP1	  ; YES, ERROR IS SET
  2938                              <1> 	;mov	al, ERR_PRN_IO
  2939 00005727 FEC0                <1> 	inc	al		  ; INDICATE I/O ERROR
  2940                              <1> PRNOP1: 
  2941                              <1> 
  2942                              <1> ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT)
  2943                              <1> 
  2944 00005729 C3                  <1> 	retn			  ; RETURN WITH ERROR
  2945                              <1>  
  2946                              <1> ; THE BITS SAID NO ERROR.
  2947                              <1> ; UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK HERE.
  2948                              <1> 
  2949                              <1> prnop_chk_nrdy:
  2950                              <1> 	;mov	al, 2		  ; ASSUME NOT-READY
  2951 0000572A B019                <1> 	mov	al, ERR_PRN_TIMEOUT ; ''time out !' error
  2952                              <1> 	
  2953 0000572C F6C401              <1> 	test	ah, TIMEOUTSTATUS ; IS TIME-OUT SET?
  2954                              <1> 				  ; IF NZ THEN ERROR, ELSE OK???
  2955                              <1> PRNOP2: 
  2956 0000572F C3                  <1> 	retn
  2957                              <1> 
  2958                              <1> 
  2959                              <1> dskw: ; / write routine for non-special files
  2960                              <1> 	;
  2961                              <1> 	; 03/02/2022
  2962                              <1> 	; 25/07/2015
  2963                              <1> 	; 16/06/2015
  2964                              <1> 	; 09/06/2015
  2965                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2966                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2967                              <1> 	;
  2968                              <1> 	; 01/08/2013 (mkdir_w check)
  2969                              <1> 
  2970                              <1> 	;push	ax ; 26/04/2013
  2971                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  2972                              <1> 	; 03/02/2022
  2973 00005730 50                  <1> 	push	eax
  2974                              <1> 	; AX = inode number
  2975 00005731 E8B3FAFFFF          <1> 	call	iget
  2976                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2977                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2978 00005736 8B1D[6C700000]      <1>         mov     ebx, [u.fofp] 
  2979 0000573C 8B13                <1> 	mov 	edx, [ebx]
  2980                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2981                              <1> 			       ; / in the fsp entry for this file] in r2
  2982 0000573E 0315[80700000]      <1> 	add 	edx, [u.count]	
  2983                              <1> 		; add u.count,r2 / no. of bytes to be written
  2984                              <1> 			       ; / + file offset is put in r2
  2985                              <1> 	; 16/06/2015        
  2986 00005744 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2987 0000574A 760F                <1> 	jna	short dskw_0
  2988 0000574C C705[AB700000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2988 00005754 0000                <1>
  2989 00005756 E978E3FFFF          <1> 	jmp	error
  2990                              <1> dskw_0:	
  2991 0000575B 663B15[5C6D0000]    <1> 	cmp     dx, [i.size]
  2992                              <1> 		; cmp r2,i.size / is this greater than the present size of
  2993                              <1> 		              ; / the file?
  2994 00005762 760C                <1> 	jna	short dskw_1
  2995                              <1> 		; blos 1f / no, branch
  2996 00005764 668915[5C6D0000]    <1>         mov     [i.size], dx
  2997                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  2998                              <1> 			      ; / file offset + no. of data bytes
  2999 0000576B E883FBFFFF          <1> 	call	setimod
  3000                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  3001                              <1> 		          ; / modified), stuff time of modification into
  3002                              <1> 	          	  ; / core image of i-node
  3003                              <1> dskw_1: ; 1:	
  3004 00005770 E80BF9FFFF          <1> 	call	mget
  3005                              <1> 	; eAX = Block number
  3006                              <1> 		; jsr r0,mget / get the block no. in which to write 
  3007                              <1> 			    ; /	the next data byte
  3008                              <1> 	; eax = block number
  3009 00005775 8B1D[6C700000]      <1> 	mov     ebx, [u.fofp]
  3010 0000577B 8B13                <1> 	mov	edx, [ebx]
  3011 0000577D 81E2FF010000        <1> 	and	edx, 1FFh  
  3012                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  3013 00005783 750C                <1> 	jnz	short dskw_2
  3014                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  3015                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  3016 00005785 813D[80700000]0002- <1> 	cmp	dword [u.count], 512
  3016 0000578D 0000                <1>
  3017                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  3018                              <1> 				  ; / an entire block? (i.e., no. of
  3019 0000578F 7305                <1> 	jnb	short dskw_3
  3020                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  3021                              <1> 			; / Yes, branch. Don't have to read block
  3022                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  3023                              <1>    		; / overwritten).
  3024 00005791 E824060000          <1> 	call	dskrd
  3025                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  3026                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  3027                              <1> dskw_3: ; 3:
  3028                              <1> 	; eAX (r1) = block/sector number
  3029 00005796 E891060000          <1> 	call	wslot
  3030                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  3031                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  3032 0000579B 803D[BD700000]00    <1> 	cmp	byte [u.kcall], 0
  3033 000057A2 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  3034                              <1> 	;
  3035 000057A4 66833D[BB700000]00  <1> 	cmp	word [u.pcount], 0
  3036 000057AC 7705                <1> 	ja	short dskw_5
  3037                              <1> dskw_4:
  3038                              <1> 	; [u.base] = virtual address to transfer (as source address)
  3039 000057AE E89BFDFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  3040                              <1> dskw_5:
  3041                              <1> 	; eBX (r5) = system (I/O) buffer address
  3042 000057B3 E87D000000          <1> 	call	sioreg
  3043                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  3044                              <1> 			     ; / r1 = address of data, r2 points to location
  3045                              <1> 			     ; / in buffer in which to start writing data
  3046                              <1> 	; eSI = file (user data) offset
  3047                              <1> 	; eDI = sector (I/O) buffer offset
  3048                              <1> 	; eCX = byte count
  3049                              <1> 	;
  3050 000057B8 F3A4                <1>   	rep	movsb
  3051                              <1> 		; movb (r1 )+,(r2)+ 
  3052                              <1> 		         ; / transfer a byte of data to the I/O buffer
  3053                              <1> 		; dec r3 / decrement no. of bytes to be written
  3054                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  3055                              <1> 	; 25/07/2015
  3056                              <1> 	; eax = remain bytes in buffer
  3057                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  3058 000057BA 09C0                <1> 	or	eax, eax
  3059 000057BC 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  3060                              <1> dskw_6:
  3061 000057BE E885060000          <1> 	call	dskwr
  3062                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  3063 000057C3 833D[80700000]00    <1>         cmp     dword [u.count], 0
  3064                              <1> 		; tst u.count / any more data to write?
  3065 000057CA 77A4                <1> 	ja	short dskw_1
  3066                              <1> 		; bne 1b / yes, branch
  3067                              <1> 	; 03/08/2013
  3068 000057CC C605[BD700000]00    <1> 	mov	byte [u.kcall], 0
  3069                              <1> 	; 20/09/2013 (;;)
  3070                              <1> 	;pop	ax
  3071                              <1> 	; 03/02/2022
  3072 000057D3 58                  <1> 	pop	eax
  3073 000057D4 C3                  <1> 	retn
  3074                              <1> 	;;jmp 	short dskw_ret 
  3075                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  3076                              <1> 
  3077                              <1> cpass: ; / get next character from user area of core and put it in r1
  3078                              <1> 	; 18/10/2015
  3079                              <1> 	; 10/10/2015
  3080                              <1> 	; 10/07/2015
  3081                              <1> 	; 02/07/2015
  3082                              <1> 	; 01/07/2015
  3083                              <1> 	; 24/06/2015
  3084                              <1> 	; 08/06/2015
  3085                              <1> 	; 04/06/2015
  3086                              <1> 	; 20/05/2015
  3087                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3088                              <1> 	;
  3089                              <1> 	; INPUTS -> 
  3090                              <1> 	;     [u.base] = virtual address in user area
  3091                              <1> 	;     [u.count] = byte count (max.)
  3092                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  3093                              <1> 	; OUTPUTS -> 
  3094                              <1> 	;     AL = the character which is pointed by [u.base]
  3095                              <1> 	;     zf = 1 -> transfer count has been completed	
  3096                              <1>         ;
  3097                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  3098                              <1> 	;
  3099                              <1> 	;
  3100 000057D5 833D[80700000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  3101                              <1> 		; tst u.count / have all the characters been transferred
  3102                              <1> 			    ; / (i.e., u.count, # of chars. left
  3103 000057DC 763F                <1> 	jna	short cpass_3
  3104                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  3105 000057DE FF0D[80700000]      <1> 	dec	dword [u.count]
  3106                              <1> 		; dec u.count / no, decrement u.count
  3107                              <1>         ; 19/05/2015 
  3108                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  3109                              <1> 	;		      to physical address
  3110 000057E4 66833D[BB700000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  3111                              <1> 			     ; 1-4095 --> use previous physical base address
  3112                              <1> 			     ; in [u.pbase]
  3113 000057EC 770E                <1> 	ja	short cpass_1
  3114                              <1> 	; 02/07/2015
  3115 000057EE 833D[B3700000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  3116 000057F5 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  3117                              <1> 	; 08/06/2015 - 10/07/2015
  3118 000057F7 E852FDFFFF          <1> 	call	trans_addr_r
  3119                              <1> cpass_1:
  3120                              <1> 	; 02/07/2015
  3121                              <1> 	; 24/06/2015
  3122 000057FC 66FF0D[BB700000]    <1> 	dec	word [u.pcount]
  3123                              <1> cpass_2: 
  3124                              <1> 	; 10/10/2015
  3125                              <1> 	; 02/07/2015
  3126 00005803 8B15[B7700000]      <1> 	mov	edx, [u.pbase]
  3127 00005809 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3128                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3129                              <1> 				; / by u.base and put it in r1
  3130 0000580B FF05[84700000]      <1> 	inc	dword [u.nread]
  3131                              <1> 		; inc u.nread / increment no. of bytes transferred
  3132 00005811 FF05[7C700000]      <1> 	inc	dword [u.base]
  3133                              <1> 		; inc u.base / increment the buffer address to point to the
  3134                              <1> 			   ; / next byte
  3135 00005817 FF05[B7700000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3136                              <1> cpass_3:
  3137 0000581D C3                  <1> 	retn
  3138                              <1> 		; rts	r0 / next byte
  3139                              <1> 	; 1: 
  3140                              <1> 		; mov (sp)+,r0 
  3141                              <1> 		         ; / put return address of calling routine into r0
  3142                              <1> 		; mov (sp)+,r1 / i-number in r1
  3143                              <1> 		; rts r0 / non-local return
  3144                              <1> cpass_k:
  3145                              <1> 	; 02/07/2015
  3146                              <1> 	; The caller is os kernel 
  3147                              <1> 	; (get sysexec arguments from kernel's memory space)
  3148                              <1> 	;
  3149 0000581E 8B1D[7C700000]      <1> 	mov	ebx, [u.base]
  3150 00005824 66C705[BB700000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3150 0000582C 10                  <1>
  3151 0000582D 891D[B7700000]      <1> 	mov	[u.pbase], ebx
  3152 00005833 EBCE                <1> 	jmp	short cpass_2
  3153                              <1> 	
  3154                              <1> sioreg: 
  3155                              <1> 	; 25/07/2015
  3156                              <1> 	; 18/07/2015
  3157                              <1> 	; 02/07/2015
  3158                              <1> 	; 17/06/2015
  3159                              <1> 	; 09/06/2015
  3160                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3161                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3162                              <1> 	;
  3163                              <1> 	; INPUTS -> 
  3164                              <1> 	;     eBX = system buffer (data) address (r5)
  3165                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3166                              <1> 	;     [u.base] = virtual address of the user buffer
  3167                              <1> 	;     [u.pbase] = physical address of the user buffer
  3168                              <1> 	;     [u.count] = byte count
  3169                              <1> 	;     [u.pcount] = byte count within page frame 			
  3170                              <1> 	; OUTPUTS -> 
  3171                              <1> 	;     eSI = user data offset (r1)
  3172                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  3173                              <1> 	;     eCX = byte count (r3)
  3174                              <1> 	;     EAX = remain bytes after byte count within page frame
  3175                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3176                              <1>         ;
  3177                              <1> 	; ((Modified registers:  EDX))
  3178                              <1>  
  3179 00005835 8B35[6C700000]      <1>         mov     esi, [u.fofp]
  3180 0000583B 8B3E                <1>         mov     edi, [esi]
  3181                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3182 0000583D 89F9                <1> 	mov	ecx, edi
  3183                              <1> 		; mov r2,r3 / and also to r3
  3184 0000583F 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3185                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3186 00005845 81E7FF010000        <1> 	and	edi, 1FFh
  3187                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3188 0000584B 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3189                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3190                              <1> 			  ; / where data is to be placed
  3191                              <1>                 ; mov u.base,r1 / address of data is in r1
  3192 0000584D F7D9                <1> 	neg	ecx
  3193                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3194                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3195 0000584F 3B0D[80700000]      <1> 	cmp	ecx, [u.count]
  3196                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3197                              <1> 			       ; / to be written to the file
  3198 00005855 7606                <1> 	jna	short sioreg_0
  3199                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3200                              <1> 			 ; / in the file block as the number to be written
  3201 00005857 8B0D[80700000]      <1> 	mov	ecx, [u.count]
  3202                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3203                              <1> 			       ; / bytes as the number to be written
  3204                              <1> sioreg_0:
  3205                              <1> 	; 17/06/2015
  3206 0000585D 803D[BD700000]00    <1> 	cmp	byte [u.kcall], 0 
  3207 00005864 7613                <1> 	jna	short sioreg_1
  3208                              <1> 	; 25/07/2015
  3209                              <1> 	; the caller is 'mkdir' or 'namei'
  3210 00005866 A1[7C700000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3211 0000586B A3[B7700000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3212 00005870 66890D[BB700000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3213 00005877 EB0B                <1> 	jmp	short sioreg_2
  3214                              <1> sioreg_1:
  3215                              <1> 	; 25/07/2015
  3216                              <1> 	; 18/07/2015
  3217                              <1> 	; 09/06/2015 
  3218 00005879 0FB715[BB700000]    <1> 	movzx	edx, word [u.pcount]
  3219                              <1> 		; ecx and [u.pcount] are always > 0, here
  3220 00005880 39D1                <1> 	cmp	ecx, edx	
  3221 00005882 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3222                              <1> sioreg_2: ; 2:
  3223 00005884 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3224                              <1> sioreg_3:
  3225 00005886 010D[84700000]      <1> 	add 	[u.nread], ecx
  3226                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3227                              <1> 			         ; / during write is put into u.nread
  3228 0000588C 290D[80700000]      <1> 	sub 	[u.count], ecx
  3229                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3230                              <1> 			       ; / must be written or read
  3231 00005892 010D[7C700000]      <1> 	add 	[u.base], ecx
  3232                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3233                              <1> 			      ; / data bytes
  3234 00005898 010E                <1>         add 	[esi], ecx 
  3235                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3236                              <1> 			       ; / + old file offset
  3237                              <1> 	; 25/07/2015
  3238 0000589A 8B35[B7700000]      <1> 	mov	esi, [u.pbase]
  3239 000058A0 66290D[BB700000]    <1> 	sub	[u.pcount], cx
  3240 000058A7 010D[B7700000]      <1> 	add	[u.pbase], ecx
  3241 000058AD C3                  <1>         retn
  3242                              <1> 		; rts r0
  3243                              <1> 		; transfer count > [u.pcount]
  3244                              <1> sioreg_4:
  3245                              <1> 	; 25/07/2015
  3246                              <1> 	; transfer count > [u.pcount] 
  3247                              <1> 	; (ecx > edx)
  3248 000058AE 89C8                <1> 	mov	eax, ecx
  3249 000058B0 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3250 000058B2 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3251 000058B4 EBD0                <1> 	jmp	short sioreg_3
  2054                                  %include 'u7.s'        ; 18/04/2015
  2055                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYS7.INC
  2056                              <1> ; Last Modification: 13/06/2022
  2057                              <1> ; ----------------------------------------------------------------------------
  2058                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2059                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2060                              <1> ;
  2061                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2062                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2063                              <1> ; <Bell Laboratories (17/3/1972)>
  2064                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2065                              <1> ;
  2066                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2067                              <1> ;
  2068                              <1> ; ****************************************************************************
  2069                              <1> ; 14/11/2015
  2070                              <1> 
  2071                              <1> sysmount: ; / mount file system; args special; name
  2072                              <1> 	; 14/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2073                              <1> 	; 12/02/2022
  2074                              <1> 	; 04/02/2022
  2075                              <1> 	; 14/11/2015
  2076                              <1> 	; 24/10/2015
  2077                              <1> 	; 13/10/2015
  2078                              <1> 	; 10/07/2015
  2079                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2080                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2081                              <1> 	;
  2082                              <1> 	; 'sysmount' anounces to the system that a removable 
  2083                              <1> 	; file system has been mounted on a special file.
  2084                              <1> 	; The device number of the special file is obtained vihha
  2085                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2086                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2087                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2088                              <1> 	; to read file system into core, i.e. the first block on the
  2089                              <1> 	; mountable file system is read in. This block is super block
  2090                              <1> 	; for the file system. This call is super user restricted.	
  2091                              <1> 	;
  2092                              <1> 	; Calling sequence:
  2093                              <1> 	;	sysmount; special; name
  2094                              <1> 	; Arguments:
  2095                              <1> 	;	special - pointer to name of special file (device)
  2096                              <1> 	;	name -  pointer to name of the root directory of the
  2097                              <1> 	;		newly mounted file system. 'name' should 
  2098                              <1> 	;		always be a directory.
  2099                              <1> 	; Inputs: - 
  2100                              <1> 	; Outputs: -
  2101                              <1> 	; ...............................................................
  2102                              <1> 	;				
  2103                              <1> 	; Retro UNIX 8086 v1 modification: 
  2104                              <1> 	;       'sysmount' system call has two arguments; so,
  2105                              <1> 	;	* 1st argument, special is pointed to by BX register
  2106                              <1> 	;	* 2nd argument, name is in CX register
  2107                              <1> 	;
  2108                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2109                              <1> 	;	       already modified for IBM PC compatibility and 
  2110                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2111                              <1> 	
  2112                              <1> 	;call	arg2
  2113                              <1> 		; jsr r0,arg2 / get arguments special and name
  2114 000058B6 891D[74700000]      <1> 	mov	[u.namep], ebx
  2115                              <1> 	; 12/02/2022
  2116                              <1> 	;push	ecx ; directory name
  2117 000058BC 66833D[46700000]00  <1> 	cmp	word [mnti], 0
  2118                              <1> 		; tst mnti / is the i-number of the cross device file
  2119                              <1> 			 ; / zero?
  2120                              <1> 	;;ja	error
  2121                              <1>         	; bne errora / no, error
  2122                              <1> 	;ja	sysmnt_err0
  2123                              <1> 	; 04/02/2022
  2124 000058C4 7605                <1> 	jna	short sysmnt_0
  2125 000058C6 E950010000          <1> 	jmp	sysmnt_err0
  2126                              <1> sysmnt_0:
  2127                              <1> 	; 12/02/2022
  2128 000058CB 51                  <1> 	push	ecx ; directory name
  2129 000058CC E859010000          <1> 	call	getspl
  2130                              <1> 		; jsr r0,getspl / get special files device number in r1
  2131                              <1> 	; 12/02/2022
  2132 000058D1 8F05[74700000]      <1> 	pop	dword [u.namep] ; directory name
  2133                              <1> 	; 13/10/2015
  2134                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2135                              <1> 	; 04/02/2022
  2136 000058D7 29DB                <1> 	sub	ebx, ebx
  2137 000058D9 88C3                <1> 	mov	bl, al
  2138 000058DB F683[DA670000]80    <1>         test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2139 000058E2 750F                <1> 	jnz	short sysmnt_1
  2140                              <1> sysmnt_err1:
  2141 000058E4 C705[AB700000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2141 000058EC 0000                <1>
  2142 000058EE E9E0E1FFFF          <1> 	jmp	error
  2143                              <1> sysmnt_1:
  2144                              <1> 	; 12/02/2022
  2145                              <1> 	;pop	dword [u.namep]
  2146                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2147                              <1> 				  ; / on the device
  2148                              <1> 	; 14/11/2015
  2149 000058F3 53                  <1> 	push	ebx ; 13/10/2015
  2150                              <1> 		; mov r1,-(sp) / save the device number
  2151                              <1>         ;
  2152 000058F4 E8DBF0FFFF          <1> 	call	namei
  2153                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2154                              <1> 		       ; ax = 0 -> file not found 	
  2155                              <1> 	;jz	error
  2156                              <1> 	;jc	error
  2157                              <1> 		; jsr r0,namei / get the i-number of the file
  2158                              <1>                	; br errora
  2159 000058F9 730F                <1> 	jnc	short sysmnt_2
  2160                              <1> sysmnt_err2:
  2161 000058FB C705[AB700000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2161 00005903 0000                <1>
  2162 00005905 E9C9E1FFFF          <1> 	jmp	error
  2163                              <1> sysmnt_2:	
  2164 0000590A 66A3[46700000]      <1> 	mov	[mnti], ax
  2165                              <1>         	; mov r1,mnti / put it in mnti
  2166                              <1> 
  2167                              <1> 	; 14/05/2022
  2168                              <1> 	; -Retro UNIX 8086/386 v1 feaure only-
  2169 00005910 66A1[3C700000]      <1> 	mov	ax, [ii]
  2170 00005916 66A3[48700000]      <1> 	mov	[mntp], ax ; parent dir inumber of [mnti]
  2171                              <1> 
  2172                              <1> 	; 04/02/2022
  2173 0000591C BB[147F0000]        <1> 	mov	ebx, sb1 ; super block buffer (of mounted disk)
  2174                              <1> sysmnt_3: ;1:
  2175                              <1>         ;cmp	byte [ebx+1], 0
  2176                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2177                              <1> 			   ; / dismountable device set?
  2178                              <1>         ;jna	short sysmnt_4		
  2179                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2180                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2181                              <1> 	;jmp	short sysmnt_3
  2182                              <1> sysmnt_4:   
  2183 00005921 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2184 00005922 A2[43700000]        <1> 	mov	[mdev], al
  2185                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2186 00005927 8803                <1> 	mov	[ebx], al
  2187                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2188                              <1> 			      ; / of the I/O queue entry
  2189                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2190                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2191 00005929 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2192                              <1> 		; bis $2000,sb1 / set the read bit
  2193                              <1> 	; Retro UNIX 386 v1 modification : 
  2194                              <1> 	;	32 bit block number at buffer header offset 4
  2195 0000592E C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2196 00005935 E859060000          <1> 	call 	diskio
  2197 0000593A 7345                <1> 	jnc	short sysmnt_5
  2198 0000593C 31C0                <1> 	xor 	eax, eax
  2199 0000593E 66A3[46700000]      <1> 	mov	[mnti], ax ; 0
  2200 00005944 A2[43700000]        <1> 	mov	[mdev], al ; 0
  2201                              <1> 	;mov	[cdev], al ; 0
  2202                              <1> 	; 12/02/2022
  2203 00005949 803D[BE700000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2204 00005950 7508                <1> 	jne	short sysmnt_err3
  2205                              <1> 	; yes, clear [u.brwdev] for next check
  2206                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2207 00005952 FE05[BE700000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2208 00005958 EB0A                <1> 	jmp	short sysmnt_err4
  2209                              <1> sysmnt_err3:	; 12/02/2022
  2210                              <1> 	; no, set [u.error] to disk read error
  2211 0000595A C705[AB700000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2211 00005962 0000                <1>
  2212                              <1> sysmnt_err4:
  2213                              <1> 	; 12/02/2022
  2214                              <1> 	; 14/11/2015
  2215 00005964 FEC8                <1> 	dec 	al
  2216 00005966 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2217 00005968 FEC0                <1> 	inc	al
  2218 0000596A 48                  <1> 	dec	eax
  2219 0000596B 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2220 0000596E E960E1FFFF          <1> 	jmp	error
  2221                              <1> sysmnt_invd:
  2222                              <1> 	; 12/02/2022
  2223 00005973 C705[AB700000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2223 0000597B 0000                <1>
  2224                              <1> 				 ;'invalid fs/superblock !' error
  2225 0000597D 30C0                <1> 	xor	al, al
  2226 0000597F EBE3                <1> 	jmp	short sysmnt_err4
  2227                              <1> 
  2228                              <1> sysmnt_5:
  2229                              <1> 	; 04/02/2022 (BugFix)
  2230                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2231                              <1> 	; (Following check is needed to prevent mounting an
  2232                              <1> 	; invalid valid file system (invalid super block).
  2233                              <1> 	; 
  2234 00005981 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2235 00005984 C0E002              <1> 	shl	al, 2 ; 4*index
  2236 00005987 8B88[BE670000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2237                              <1> 	;;shl 	ecx, 3 ; !!!
  2238                              <1> 	; 04/02/2022
  2239 0000598D C1E903              <1> 	shr 	ecx, 3 ; (8 sectors per 1 fbm byte)
  2240                              <1> 	; ecx = number of free map bytes (required)
  2241                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2242 00005990 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)
  2243                              <1> 	; ! Buffer header is 8 bytes (Retro UNIX 386 v1 and v1.1) !
  2244                              <1> 	;;movzx	edx, word [sb1+4] ; the 1st data word ; !!!
  2245 00005994 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2246                              <1> 			 ; (in sectors), if they are not equal
  2247                              <1> 			 ; the disk to be mounted is an...	
  2248 00005996 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2249                              <1> 			 ; (which has not got a valid super block)
  2250                              <1> 	;
  2251 00005998 C6430100            <1> 	mov	byte [ebx+1], 0
  2252                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2253                              <1> ;sysmnt_6: ;1:
  2254                              <1> 	;;cmp	byte [sb1+1], 0
  2255                              <1> 		; tstb sb1+1 / done reading?
  2256                              <1>    	;;jna	sysret
  2257                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2258                              <1> 	;;jmp	short sysmnt_6
  2259                              <1> 		;bne 1b / no, wait
  2260                              <1>         	;br sysreta / yes
  2261 0000599C E952E1FFFF          <1> 	jmp	sysret
  2262                              <1> 
  2263                              <1> sysumount: ; / special dismount file system,
  2264                              <1> 	; 15/05/2022
  2265                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2266                              <1> 	; 04/02/2022
  2267                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2268                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2269                              <1> 	;
  2270                              <1> 	; 04/11/2013
  2271                              <1> 	; 09/07/2013
  2272                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2273                              <1> 	; indicated as an argument is no longer contain a removable
  2274                              <1> 	; file system. 'getspl' gets the device number of the special
  2275                              <1> 	; file. If no file system was mounted on that device an error
  2276                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2277                              <1> 	; to 'sysret'.
  2278                              <1> 	;
  2279                              <1> 	; Calling sequence:
  2280                              <1> 	;	sysmount; special
  2281                              <1> 	; Arguments:
  2282                              <1> 	;	special - special file to dismount (device)
  2283                              <1> 	;
  2284                              <1> 	; Inputs: - 
  2285                              <1> 	; Outputs: -
  2286                              <1> 	; ...............................................................
  2287                              <1> 	;				
  2288                              <1> 	; Retro UNIX 8086 v1 modification: 
  2289                              <1> 	;       'sysumount' system call has one argument; so,
  2290                              <1> 	;	* Single argument, special is pointed to by BX register
  2291                              <1> 	;
  2292                              <1> 	
  2293                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2294                              <1> 	;call	arg
  2295                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2296 000059A1 891D[74700000]      <1>         mov	[u.namep], ebx
  2297 000059A7 E87E000000          <1> 	call	getspl
  2298                              <1> 		; jsr r0,getspl / get the device number in r1
  2299                              <1> 	;;;
  2300                              <1> 	; 09/05/2022 - Erdogan Tan
  2301                              <1> 	; (I have added [mnti] check because
  2302                              <1> 	;  retro unix device number of /dev/fd0 is 0
  2303                              <1> 	;  .. so, 'cmp al, [mdev]' is not enough
  2304                              <1> 	;  for dismounting /dev/fd0. sysumount system call would give
  2305                              <1> 	;  wrong cf=0 result while /dev/fd0 is not mounted.)
  2306 000059AC 66833D[46700000]00  <1> 	cmp	word [mnti], 0
  2307 000059B4 7665                <1> 	jna	short sysmnt_err0 ; there is not a mounted device !
  2308                              <1> 	;;;
  2309                              <1> 
  2310 000059B6 3A05[43700000]      <1> 	cmp	al, [mdev]
  2311                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2312 000059BC 755D                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2313                              <1> 	;jne	error
  2314                              <1>         	; bne errora / no error
  2315 000059BE 30C0                <1> 	xor	al, al ; ah = 0
  2316                              <1> sysumnt_0: ;1:
  2317                              <1>      	; 04/02/2022
  2318                              <1> 	;cmp 	[sb1+1], al ; 0
  2319                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2320                              <1> 	;		   ; / (inhibit bit set)?
  2321                              <1> 	;jna	short sysumnt_1		
  2322                              <1> 	;	; bne 1b / yes, wait
  2323                              <1> 	;call	idle ; (wait for hardware interrupt)
  2324                              <1> 	;jmp	short sysumnt_0
  2325                              <1> sysumnt_1:
  2326                              <1> 	; 15/05/2022
  2327                              <1> 	; change user's current directory to mounting directory
  2328                              <1> 	; if it is on the mounted device (chdir back to root fs)
  2329 000059C0 3805[A0700000]      <1> 	cmp	byte [u.cdrv], al ; 0
  2330 000059C6 7643                <1> 	jna	short sysumnt_4
  2331                              <1> 	;;;
  2332                              <1> 	; 15/05/2022
  2333                              <1> 	; It is needed to change the parent process's current
  2334                              <1> 	; directory because shell runs (/etc/umount) 
  2335                              <1> 	; as child process.
  2336 000059C8 31DB                <1> 	xor	ebx, ebx 
  2337 000059CA 8A1D[A5700000]      <1> 	mov	bl, [u.uno]
  2338 000059D0 D0E3                <1> 	shl	bl, 1 ; >= 2 .. <= 32
  2339 000059D2 81C3[966D0000]      <1> 	add	ebx, p.ppid-2
  2340 000059D8 668B13              <1> 	mov	dx, [ebx] ; process id of the parent [p.ppid]	
  2341 000059DB BE[786D0000]        <1> 	mov	esi, p.pid
  2342 000059E0 29C9                <1> 	sub	ecx, ecx
  2343 000059E2 B110                <1> 	mov	cl, nproc ; 16  
  2344                              <1> sysumnt_2:	
  2345 000059E4 66AD                <1> 	lodsw
  2346 000059E6 6639D0              <1> 	cmp	ax, dx
  2347 000059E9 7402                <1> 	je	short sysumnt_3
  2348 000059EB E2F7                <1> 	loop	sysumnt_2
  2349                              <1> sysumnt_3:
  2350 000059ED 31C0                <1> 	xor	eax, eax
  2351 000059EF 81EE[786D0000]      <1> 	sub	esi, p.pid
  2352 000059F5 D1E6                <1> 	shl	esi, 1
  2353 000059F7 8B9E[E46D0000]      <1> 	mov	ebx, [esi+p.upage-4] ; the parent's upage
  2354                              <1> 	; ebx points to user (u) structure in upage
  2355 000059FD 668B15[46700000]    <1> 	mov	dx, [mnti]
  2356                              <1> 	;mov	[u.cdir], dx
  2357                              <1> 	;mov	[u.cdrv], al ; 0
  2358 00005A04 6689530C            <1> 	mov	[ebx+u.cdir-user], dx
  2359 00005A08 88434C              <1> 	mov	[ebx+u.cdrv-user], al ; 0
  2360                              <1> 	;;;
  2361                              <1> sysumnt_4: 
  2362 00005A0B A2[43700000]        <1> 	mov	[mdev], al ; 0
  2363                              <1> 	     	; clr mntd / no, clear these
  2364 00005A10 66A3[46700000]      <1>    	mov	[mnti], ax ; 0
  2365                              <1>         	; clr mnti
  2366                              <1> 
  2367                              <1> 	;; 15/05/2022
  2368                              <1> 	;mov	[cdev], al ; 0 ; [u.cdrv] = 0
  2369                              <1> 	;mov	ax, dx  ; [u.cdir]
  2370                              <1> 	;call	iget		
  2371                              <1> 
  2372 00005A16 E9D8E0FFFF          <1>         jmp	sysret
  2373                              <1> 		; br sysreta / return
  2374                              <1> 
  2375                              <1> sysmnt_err0:
  2376 00005A1B C705[AB700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2376 00005A23 0000                <1>
  2377 00005A25 E9A9E0FFFF          <1> 	jmp	error
  2378                              <1> 
  2379                              <1> getspl: ; / get device number from a special file name
  2380 00005A2A E8A5EFFFFF          <1> 	call	namei
  2381                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2382                              <1> 		       ; ax = 0 -> file not found 	
  2383                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2384                              <1> 	; 04/02/2022
  2385 00005A2F 7305                <1> 	jnc	short getspl_0
  2386 00005A31 E9C5FEFFFF          <1> 	jmp	sysmnt_err2
  2387                              <1> getspl_0:
  2388                              <1> 	;jz	error
  2389                              <1> 	;jc	error
  2390                              <1> 		; jsr r0,namei / get the i-number of the special file
  2391                              <1>                 ; br errora / no such file
  2392 00005A36 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2393                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2394                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2395 00005A3A 72DF                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2396                              <1> 	;jc	error
  2397                              <1> 		; ble errora / less than 0?  yes, error
  2398 00005A3C 6683F805            <1>         cmp	ax, 5 ;
  2399                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2400                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2401                              <1> 	;;ja	error
  2402                              <1>         ;	; bgt errora / yes, error
  2403                              <1>         ; 04/02/2022
  2404 00005A40 7600                <1> 	jna	short getspl_retn
  2405                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2406                              <1> ;iopen_retn:
  2407                              <1> ;	retn
  2408                              <1> 		; rts r0 / return with device number in r1
  2409                              <1> ;sysmnt_err0:
  2410                              <1> ;	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2411                              <1> ;	jmp	error
  2412                              <1> 
  2413                              <1> getspl_retn:
  2414                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2415                              <1> 	; 04/02/2022
  2416                              <1> iopen_retn:
  2417 00005A42 C3                  <1> 	retn
  2418                              <1> 
  2419                              <1> iopen:
  2420                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2421                              <1> 	;		(Printer initialization)
  2422                              <1> 	; 04/02/2022
  2423                              <1> 	; 19/05/2015
  2424                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2425                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2426                              <1> 	;
  2427                              <1> 	; open file whose i-number is in r1
  2428                              <1> 	; 
  2429                              <1> 	; INPUTS ->
  2430                              <1> 	;    r1 - inode number
  2431                              <1> 	; OUTPUTS ->
  2432                              <1> 	;    file's inode in core	
  2433                              <1> 	;    r1 - inode number (positive)
  2434                              <1> 	;
  2435                              <1> 	; ((AX = R1))
  2436                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2437                              <1> 	;        
  2438                              <1> ; / open file whose i-number is in r1
  2439 00005A43 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2440                              <1> 		; tst r1 / write or read access?
  2441 00005A46 7568                <1>         jnz	short iopen_2
  2442                              <1> 		; blt 2f / write, go to 2f
  2443 00005A48 B202                <1> 	mov	dl, 2 ; read access
  2444 00005A4A E86EF8FFFF          <1> 	call	access
  2445                              <1>         	; jsr r0,access; 2 
  2446                              <1> 	; / get inode into core with read access
  2447                              <1> 	; DL=2
  2448                              <1> iopen_0:
  2449 00005A4F 6683F828            <1>         cmp	ax, 40
  2450                              <1> 		; cmp r1,$40. / is it a special file
  2451 00005A53 77ED                <1>         ja	short iopen_retn
  2452                              <1> 		; bgt 3f / no. 3f
  2453                              <1> 	; 04/02/2022
  2454 00005A55 50                  <1> 	push	eax
  2455                              <1> 	;push	ax
  2456                              <1> 		; mov r1,-(sp) / yes, figure out
  2457 00005A56 0FB6D8              <1> 	movzx	ebx, al
  2458 00005A59 C0E302              <1> 	shl	bl, 2 ; * 4 ; 04/02/2022
  2459                              <1> 	;shl	bx, 2
  2460                              <1> 		; asl r1
  2461 00005A5C 81C3[605A0000]      <1>         add     ebx, iopen_1 - 4
  2462 00005A62 FF23                <1> 	jmp	dword [ebx]
  2463                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2464                              <1> iopen_1: ; 1:
  2465 00005A64 [C85A0000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2466                              <1>  		 ;otty / tty ; r1=2
  2467                              <1>         	 ;oppt / ppt ; r1=4
  2468 00005A68 [805B0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2469                              <1> 		 ;sret / mem ; r1=6
  2470                              <1> 		 ;sret / rf0
  2471                              <1>         	 ;sret / rk0
  2472                              <1>         	 ;sret / tap0
  2473                              <1>         	 ;sret / tap1
  2474                              <1>         	 ;sret / tap2
  2475                              <1>         	 ;sret / tap3
  2476                              <1>         	 ;sret / tap4
  2477                              <1>         	 ;sret / tap5
  2478                              <1>         	 ;sret / tap6
  2479                              <1>         	 ;sret / tap7
  2480 00005A6C [805B0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2481 00005A70 [805B0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2482 00005A74 [805B0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2483 00005A78 [805B0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2484 00005A7C [805B0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2485 00005A80 [805B0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2486                              <1> 	;;dd	error ; lpr, AX = 9 (error !)
  2487                              <1>         ;dd	sret ; lpr, AX = 9 (runix)
  2488                              <1> 	; 13/06/2022 - (lpt_init)
  2489 00005A84 [4C5C0000]          <1>         dd	ejec ; lpr, AX = 9 (runix)
  2490 00005A88 [D95A0000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2491                              <1> 		 ;ocvt / tty0
  2492 00005A8C [D95A0000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2493                              <1> 		 ;ocvt / tty1
  2494 00005A90 [D95A0000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2495                              <1> 		 ;ocvt / tty2
  2496 00005A94 [D95A0000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2497                              <1> 		 ;ocvt / tty3
  2498 00005A98 [D95A0000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2499                              <1> 		 ;ocvt / tty4
  2500 00005A9C [D95A0000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2501                              <1> 		 ;ocvt / tty5
  2502 00005AA0 [D95A0000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2503                              <1> 		 ;ocvt / tty6
  2504 00005AA4 [D95A0000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2505                              <1> 		 ;ocvt / tty7
  2506 00005AA8 [D95A0000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2507                              <1> 		 ;error / crd
  2508 00005AAC [D95A0000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2509                              <1> 
  2510                              <1> iopen_2: ; 2: / check open write access
  2511 00005AB0 66F7D8              <1> 	neg	ax
  2512                              <1> 		; neg r1 / make inode number positive
  2513 00005AB3 B201                <1> 	mov	dl, 1 ; write access
  2514 00005AB5 E803F8FFFF          <1> 	call	access
  2515                              <1> 		; jsr r0,access; 1 / get inode in core
  2516                              <1> 	; DL=1
  2517                              <1> 	; 04/02/2022
  2518 00005ABA F605[596D0000]40    <1> 	test	byte [i.flgs+1], 40h
  2519                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2520                              <1>  		; bit $40000,i.flgs / is it a directory?
  2521 00005AC1 748C                <1> 	jz	short iopen_0
  2522                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2523                              <1> 	;jmp	error ; permission denied !
  2524 00005AC3 E953FFFFFF          <1> 	jmp	sysmnt_err0
  2525                              <1> 	;;jnz	error		
  2526                              <1>        		; bne 2f / yes, transfer (error)
  2527                              <1>         ;;jmp	short iopen_0
  2528                              <1> 	;cmp	ax, 40
  2529                              <1> 		; cmp r1,$40. / no, is it a special file?
  2530                              <1>         ;ja	short iopen_2
  2531                              <1> 		; bgt 3f / no, return
  2532                              <1> 	;push	ax
  2533                              <1> 		; mov r1,-(sp) / yes
  2534                              <1> 	;movzx	ebx, al
  2535                              <1> 	;shl	bx, 1
  2536                              <1> 		; asl r1
  2537                              <1> 	;add	ebx, ipen_3 - 2
  2538                              <1> 	;jmp	dword [ebx]
  2539                              <1> 		; jmp *1f-2(r1) / figure out 
  2540                              <1> 			; / which special file it is and transfer
  2541                              <1> ;iopen_3: ; 1:
  2542                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2543                              <1>  		 ;otty / tty ; r1=2
  2544                              <1>         	 ;leadr / ppt ; r1=4
  2545                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2546                              <1> 		 ;sret / mem ; r1=6
  2547                              <1> 		 ;sret / rf0
  2548                              <1>         	 ;sret / rk0
  2549                              <1>         	 ;sret / tap0
  2550                              <1>         	 ;sret / tap1
  2551                              <1>         	 ;sret / tap2
  2552                              <1>         	 ;sret / tap3
  2553                              <1>         	 ;sret / tap4
  2554                              <1>         	 ;sret / tap5
  2555                              <1>         	 ;sret / tap6
  2556                              <1>         	 ;sret / tap7
  2557                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2558                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2559                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2560                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2561                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2562                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2563                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2564                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2565                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2566                              <1> 		 ;ocvt / tty0
  2567                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2568                              <1> 		 ;ocvt / tty1
  2569                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2570                              <1> 		 ;ocvt / tty2
  2571                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2572                              <1> 		 ;ocvt / tty3
  2573                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2574                              <1> 		 ;ocvt / tty4
  2575                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2576                              <1> 		 ;ocvt / tty5
  2577                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2578                              <1> 		 ;ocvt / tty6
  2579                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2580                              <1> 		 ;ocvt / tty7
  2581                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2582                              <1> 		 ;/ ejec / lpr
  2583                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2584                              <1> 
  2585                              <1> otty: ;/ open console tty for reading or writing
  2586                              <1> 	; 03/03/2022
  2587                              <1> 	; 02/03/2022
  2588                              <1> 	; 27/02/2022
  2589                              <1> 	; 23/02/2022
  2590                              <1> 	; 22/02/2022
  2591                              <1> 	; 04/02/2022
  2592                              <1> 	; 16/11/2015
  2593                              <1> 	; 12/11/2015
  2594                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2595                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2596                              <1> 	; 16/07/2013
  2597                              <1> 	; Retro UNIX 8086 v1 modification:
  2598                              <1> 	;  If a tty is open for read or write by
  2599                              <1> 	;     a process (u.uno), only same process can open
  2600                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2601                              <1> 	;
  2602                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2603                              <1> 	;
  2604 00005AC8 0FB61D[A5700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2605 00005ACF 8A83[B76D0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2606                              <1> 	; 13/01/2014
  2607                              <1> 	;jmp	short ottyp
  2608                              <1> 	; 23/02/2022
  2609 00005AD5 88C4                <1> 	mov	ah, al
  2610 00005AD7 EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2611                              <1> ocvt:
  2612 00005AD9 2C0A                <1> 	sub	al, 10
  2613                              <1> 	; 04/02/2022
  2614 00005ADB 31DB                <1> 	xor	ebx, ebx
  2615                              <1> ottyp:
  2616                              <1> 	; 23/02/2022
  2617 00005ADD B4FF                <1> 	mov	ah, 0FFh
  2618                              <1> ottypc:
  2619                              <1> 	; 03/03/2022
  2620                              <1> 	; 23/02/2022
  2621                              <1> 	; 22/02/2022
  2622                              <1> 	; 12/02/2022
  2623                              <1> 	; 04/02/2022
  2624                              <1> 	; 16/11/2015
  2625                              <1> 	; 12/11/2015
  2626                              <1> 	; 18/05/2015 (32 bit modifications)
  2627                              <1> 	; 06/12/2013 - 13/07/2014
  2628 00005ADF 88C6                <1> 	mov	dh, al ; tty number
  2629                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2630                              <1> 	; 04/02/2022
  2631 00005AE1 88C3                <1> 	mov	bl, al
  2632 00005AE3 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2633                              <1> 	; 26/01/2014	
  2634 00005AE5 81C3[E46C0000]      <1> 	add 	ebx, ttyl
  2635 00005AEB 668B0B              <1> 	mov 	cx, [ebx]
  2636                              <1> 		   ; CL = lock value (0 or process number)
  2637                              <1> 		   ; CH = open count 
  2638 00005AEE 20C9                <1> 	and 	cl, cl
  2639                              <1> 	; 13/01/2014
  2640                              <1> 	;jz 	short otty_ret
  2641                              <1> 	; 04/02/2022
  2642 00005AF0 7447                <1> 	jz 	short ottys_0
  2643                              <1> 	;
  2644                              <1> 	; 16/11/2015
  2645 00005AF2 3A0D[A5700000]      <1> 	cmp 	cl, [u.uno]
  2646 00005AF8 746E                <1> 	je	short ottys_3
  2647                              <1> 	;
  2648                              <1> 	; 23/02/2022
  2649                              <1> 	; (is it the console tty of the current process?)
  2650                              <1> 	; ((fast check/permit for console tty open function))
  2651 00005AFA 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2652 00005AFC 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2653                              <1> 	;
  2654                              <1> 	; 22/02/2022
  2655                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2656                              <1> 	;shl 	bl, 1
  2657                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2658                              <1> 	;;movzx ebx, byte [u.uno]
  2659                              <1> 	;mov	bl, [u.uno]
  2660                              <1> 	;shl 	bl, 1
  2661                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2662                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2663                              <1> 	; 22/02/2022 (BugFix) ; *
  2664 00005AFE 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2665 00005B01 D1E6                <1> 	shl 	esi, 1
  2666 00005B03 668B86[766D0000]    <1> 	mov 	ax, [esi+p.pid-2]
  2667 00005B0A 96                  <1> 	xchg	esi, eax
  2668 00005B0B A0[A5700000]        <1> 	mov	al, [u.uno]
  2669 00005B10 D0E0                <1> 	shl 	al, 1
  2670 00005B12 663BB0[966D0000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2671 00005B19 744D                <1> 	je 	short ottys_3 ; *
  2672                              <1> 	; 23/02/2022
  2673                              <1> 	; check console tty of the process
  2674                              <1> 	; (open permission must be given if the -requested- tty is
  2675                              <1> 	;  console tty of current process)
  2676 00005B1B D0E8                <1> 	shr	al, 1
  2677 00005B1D 38B0[B76D0000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2678 00005B23 7443                <1> 	je 	short ottys_3
  2679                              <1> 	;
  2680                              <1> 	; the tty is locked by another process
  2681                              <1> 	; except the parent process (p.ppid)
  2682                              <1>         ;
  2683                              <1> 	; 09/02/2022
  2684                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2685                              <1> 	;		; permission denied ! error
  2686                              <1> otty_err: ; 13/01/2014
  2687                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2688                              <1> 	;;jnz	error
  2689                              <1> 	; 04/02/2022
  2690                              <1> 	;jz	short otty_stc_retn
  2691                              <1> 	;jmp	error
  2692                              <1> 	; 12/02/2022
  2693 00005B25 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2694 00005B28 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2695                              <1> 	; iopen (dl=1 or dl=2)
  2696 00005B2A C705[AB700000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2696 00005B32 0000                <1>
  2697                              <1> 			; permission denied ! error
  2698 00005B34 E99ADFFFFF          <1> 	jmp	error
  2699                              <1> ;otty_stc_retn:
  2700                              <1> 	;stc
  2701                              <1> 	;retn
  2702                              <1> ottys_0:
  2703                              <1> 	; 04/02/2022
  2704                              <1> otty_ret: 
  2705                              <1> 	; 13/01/2014
  2706 00005B39 80FE07              <1> 	cmp 	dh, 7
  2707 00005B3C 7624                <1> 	jna	short ottys_2
  2708                              <1> 	; 16/11/2015
  2709                              <1> com_port_check:
  2710 00005B3E BE[026D0000]        <1> 	mov	esi, com1p
  2711 00005B43 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2712 00005B46 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2713 00005B48 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2714                              <1> ottys_1:
  2715                              <1> 	; 12/11/2015
  2716 00005B49 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2717 00005B4C 7714                <1> 	ja	short com_port_ready
  2718                              <1> 	;
  2719                              <1> 	; 12/02/2022
  2720 00005B4E 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2721 00005B51 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2722 00005B53 C705[AB700000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2722 00005B5B 0000                <1>
  2723                              <1> 			   ; device not ready ! error
  2724                              <1> 	;jmp	short otty_err
  2725 00005B5D E971DFFFFF          <1> 	jmp	error
  2726                              <1> com_port_ready:
  2727                              <1> ottys_2:
  2728                              <1> 	; 02/03/2022
  2729                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2730                              <1> 	;jnz	short ottys_3
  2731 00005B62 8A0D[A5700000]      <1> 	mov	cl, [u.uno]
  2732                              <1> ottys_3:
  2733 00005B68 FEC5                <1> 	inc 	ch
  2734 00005B6A 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2735                              <1> 	; 06/12/2013
  2736 00005B6D FEC6                <1> 	inc	dh	; tty number + 1
  2737 00005B6F BB[8C700000]        <1> 	mov	ebx, u.ttyp
  2738                              <1> 	; 13/01/2014
  2739 00005B74 F6C202              <1> 	test	dl, 2	; open for read sign
  2740 00005B77 7501                <1> 	jnz	short ottys_4
  2741 00005B79 43                  <1> 	inc	ebx
  2742                              <1> ottys_4:
  2743                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2744 00005B7A 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2745                              <1> 	; 27/02/2022
  2746 00005B7C 08D2                <1> 	or	dl, dl	; sysstty system call check (DL=0)
  2747 00005B7E 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2748                              <1> sret:
  2749                              <1> 	;pop 	ax
  2750                              <1> 	; 04/02/2022
  2751 00005B80 58                  <1> 	pop	eax
  2752                              <1> otty_retn:	; 12/02/2022
  2753                              <1> iclose_retn:	
  2754 00005B81 C3                  <1> 	retn
  2755                              <1> 
  2756                              <1> 	;
  2757                              <1> 	; Original UNIX v1 'otty' routine:
  2758                              <1> 	;	
  2759                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2760                              <1>         ;                 / reader status reg
  2761                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2762                              <1>         ;                 / punch status reg
  2763                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2764                              <1>         ;                          / console tty buffer
  2765                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2766                              <1>         ;            / console tty
  2767                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2768                              <1>         ;             / buffer header
  2769                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2770                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2771                              <1>         ;                 / tty
  2772                              <1>         ;br     sret / ?
  2773                              <1> ;sret:
  2774                              <1> 		; clr *$ps / set processor priority to zero
  2775                              <1> ;	pop	ax
  2776                              <1>         	; mov (sp)+,r1 / pop stack to r1
  2777                              <1> ;3:
  2778                              <1> ;	retn
  2779                              <1>         	; rts r0
  2780                              <1> 	
  2781                              <1> ;ocvt:	; < open tty >
  2782                              <1> 	; 13/01/2014
  2783                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2784                              <1> 	; 24/09/2013 consistency check -> ok
  2785                              <1> 	; 16/09/2013
  2786                              <1> 	; 03/09/2013
  2787                              <1> 	; 27/08/2013
  2788                              <1> 	; 16/08/2013
  2789                              <1> 	; 16/07/2013
  2790                              <1> 	; 27/05/2013
  2791                              <1> 	; 21/05/2013
  2792                              <1> 	;
  2793                              <1> 	; Retro UNIX 8086 v1 modification !
  2794                              <1> 	; 
  2795                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2796                              <1> 	;		(exactly different than this one)
  2797                              <1> 	;	was in 'u9.s' file.
  2798                              <1> 	;
  2799                              <1> 	; 16/07/2013
  2800                              <1> 	; Retro UNIX 8086 v1 modification:
  2801                              <1> 	;  If a tty is open for read or write by
  2802                              <1> 	;     a process (u.uno), only same process can open
  2803                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2804                              <1> 	;
  2805                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2806                              <1> 
  2807                              <1> 	; 16/09/2013
  2808                              <1> 	; sub 	al, 10
  2809                              <1> 	
  2810                              <1> 	; 06/12/2013
  2811                              <1> 	;cmp	al, 7
  2812                              <1>         ;jna     short ottyp
  2813                              <1> 	; 13/01/2014
  2814                              <1> 	;jmp	short ottyp
  2815                              <1> 
  2816                              <1> 
  2817                              <1> ;oppt: / open paper tape for reading or writing
  2818                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2819                              <1> ;        tstb   pptiflg / is file already open
  2820                              <1> ;        bne    2f / yes, branch
  2821                              <1> ;1:
  2822                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2823                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2824                              <1> ;               br .+4 / for paper tape input and place in free list
  2825                              <1> ;        br     1b
  2826                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2827                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2828                              <1> ;        br     sret
  2829                              <1> ;2:
  2830                              <1> ;        jmp    error / file already open
  2831                              <1> 
  2832                              <1> iclose: 
  2833                              <1> 	; 04/02/2022
  2834                              <1> 	; 19/05/2015
  2835                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2836                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2837                              <1> 	;
  2838                              <1> 	; close file whose i-number is in r1
  2839                              <1> 	; 
  2840                              <1> 	; INPUTS ->
  2841                              <1> 	;    r1 - inode number
  2842                              <1> 	; OUTPUTS ->
  2843                              <1> 	;    file's inode in core	
  2844                              <1> 	;    r1 - inode number (positive)
  2845                              <1> 	;
  2846                              <1> 	; ((AX = R1))
  2847                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2848                              <1> 	;        
  2849                              <1> ;/ close file whose i-number is in r1
  2850 00005B82 B202                <1> 	mov	dl, 2 ; 12/01/2014
  2851 00005B84 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2852                              <1> 		; tst r1 / test i-number
  2853                              <1>         ;jnz	short iclose_2
  2854                              <1> 		; blt 2f / if neg., branch
  2855 00005B87 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2856                              <1> 	; 16/07/2013 
  2857 00005B89 66F7D8              <1> 	neg	ax ; make it positive
  2858                              <1> 	; 12/01/2014
  2859 00005B8C FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2860                              <1> iclose_0:
  2861 00005B8E 6683F828            <1> 	cmp	ax, 40
  2862                              <1> 		; cmp r1,$40. / is it a special file
  2863 00005B92 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2864                              <1> 		; bgt 3b / no, return
  2865                              <1> 	; 12/01/2014
  2866                              <1> 	; DL=2 -> special file was opened for reading
  2867                              <1> 	; DL=1 -> special file was opened for writing
  2868                              <1> 	; 04/02/2022
  2869 00005B94 50                  <1> 	push	eax
  2870                              <1> 	;push	ax
  2871                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2872 00005B95 0FB6D8              <1> 	movzx	ebx, al
  2873                              <1> 	; 04/02/2022
  2874 00005B98 C0E302              <1> 	shl	bl, 2
  2875                              <1> 	;shl	bx, 2
  2876                              <1> 		; asl r1
  2877 00005B9B 81C3[9F5B0000]      <1> 	add	ebx, iclose_1 - 4
  2878 00005BA1 FF23                <1> 	jmp	dword [ebx]
  2879                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2880                              <1> iclose_1 :
  2881 00005BA3 [EF5B0000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2882 00005BA7 [4A5C0000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2883 00005BAB [4A5C0000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2884 00005BAF [4A5C0000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2885 00005BB3 [4A5C0000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2886 00005BB7 [4A5C0000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2887 00005BBB [4A5C0000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2888 00005BBF [4A5C0000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2889 00005BC3 [4A5C0000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2890                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2891                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2892 00005BC7 [FE5B0000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2893 00005BCB [FE5B0000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2894 00005BCF [FE5B0000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2895 00005BD3 [FE5B0000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2896 00005BD7 [FE5B0000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2897 00005BDB [FE5B0000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2898 00005BDF [FE5B0000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2899 00005BE3 [FE5B0000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2900 00005BE7 [FE5B0000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2901 00005BEB [FE5B0000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2902                              <1> 
  2903                              <1> 	; 1:
  2904                              <1> 	;        ctty   / tty
  2905                              <1> 	;        cppt   / ppt
  2906                              <1> 	;        sret   / mem
  2907                              <1> 	;        sret   / rf0
  2908                              <1> 	;        sret   / rk0
  2909                              <1> 	;        sret   / tap0
  2910                              <1> 	;        sret   / tap1
  2911                              <1> 	;        sret   / tap2
  2912                              <1> 	;        sret   / tap3
  2913                              <1> 	;        sret   / tap4
  2914                              <1> 	;        sret   / tap5
  2915                              <1> 	;        sret   / tap6
  2916                              <1> 	;        sret   / tap7
  2917                              <1> 	;        ccvt   / tty0
  2918                              <1> 	;        ccvt   / tty1
  2919                              <1> 	;        ccvt   / tty2
  2920                              <1> 	;        ccvt   / tty3
  2921                              <1> 	;        ccvt   / tty4
  2922                              <1> 	;        ccvt   / tty5
  2923                              <1> 	;        ccvt   / tty6
  2924                              <1> 	;        ccvt   / tty7
  2925                              <1> 	;        error / crd
  2926                              <1> 
  2927                              <1> ;iclose_2: ; 2: / negative i-number
  2928                              <1> 	;neg	ax
  2929                              <1> 		;neg r1 / make it positive
  2930                              <1> 	;cmp	ax, 40
  2931                              <1> 		;cmp r1,$40. / is it a special file?
  2932                              <1>         ;ja	short @b
  2933                              <1> 		;bgt    3b / no. return
  2934                              <1> 	;push	ax
  2935                              <1> 		;mov r1,-(sp)
  2936                              <1> 	;movzx	ebx, al
  2937                              <1> 	;shl	bx, 1
  2938                              <1> 		;asl r1 / yes. compute jump address and transfer
  2939                              <1> 	;add	ebx, iclose_3 - 2
  2940                              <1> 	;jmp	dword [ebx]
  2941                              <1> 		;jmp *1f-2(r1) / figure out 
  2942                              <1> ;iclose_3:
  2943                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2944                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2945                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2946                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2947                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2948                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2949                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2950                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2951                              <1> 	 ;dd	sret ; lpr, AX = 9	
  2952                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2953                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2954                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  2955                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  2956                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  2957                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  2958                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  2959                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  2960                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  2961                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  2962                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  2963                              <1> 	
  2964                              <1> 	;1:
  2965                              <1> 	;      	ctty   / tty
  2966                              <1> 	;       leadr  / ppt
  2967                              <1> 	;       sret   / mem
  2968                              <1> 	;       sret   / rf0
  2969                              <1> 	;       sret   / rk0
  2970                              <1> 	;       sret   / tap0
  2971                              <1> 	;       sret   / tap1
  2972                              <1> 	;       sret   / tap2
  2973                              <1> 	;       sret   / tap3
  2974                              <1> 	;       sret   / tap4
  2975                              <1> 	;       sret   / tap5
  2976                              <1> 	;       sret   / tap6
  2977                              <1> 	;       sret   / tap7
  2978                              <1> 	;       ccvt   / tty0
  2979                              <1> 	;       ccvt   / tty1
  2980                              <1> 	;       ccvt   / tty2
  2981                              <1> 	;       ccvt   / tty3
  2982                              <1> 	;       ccvt   / tty4
  2983                              <1> 	;       ccvt   / tty5
  2984                              <1> 	;       ccvt   / tty6
  2985                              <1> 	;       ccvt   / tty7
  2986                              <1> 	;/       ejec / lpr
  2987                              <1> 
  2988                              <1> ctty: ; / close console tty
  2989                              <1> 	; 25/02/2022
  2990                              <1> 	; 12/02/2022
  2991                              <1> 	; 05/02/2022
  2992                              <1> 	; 04/02/2022
  2993                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2994                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  2995                              <1> 	;
  2996                              <1> 	; Retro UNIX 8086 v1 modification !
  2997                              <1> 	; (DL = 2 -> it is open for reading)
  2998                              <1> 	; (DL = 1 -> it is open for writing)
  2999                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3000                              <1> 	;
  3001                              <1> 	; 06/12/2013
  3002 00005BEF 0FB61D[A5700000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3003 00005BF6 8A83[B76D0000]      <1>         mov     al, [ebx+p.ttyc-1]
  3004                              <1> 	; 13/01/2014
  3005                              <1> 	;jmp	short cttyp
  3006                              <1> 	; 05/02/2022
  3007 00005BFC EB04                <1> 	jmp	short ctty_0
  3008                              <1> ccvt:
  3009 00005BFE 2C0A                <1> 	sub 	al, 10
  3010                              <1> cttyp:	; (call from sysstty)
  3011                              <1> 	; 08/01/2022
  3012 00005C00 31DB                <1> 	xor	ebx, ebx
  3013                              <1> ctty_0:	
  3014                              <1> 	; 18/05/2015 (32 bit modifications)
  3015                              <1> 	; 16/08/2013 - 26/01/2014
  3016                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3017                              <1> 	; 04/02/2022
  3018 00005C02 88C3                <1> 	mov	bl, al
  3019 00005C04 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3020                              <1> 	; 26/01/2014
  3021 00005C06 81C3[E46C0000]      <1> 	add 	ebx, ttyl
  3022 00005C0C 88C6                <1> 	mov 	dh, al ; tty number
  3023 00005C0E 668B03              <1> 	mov 	ax, [ebx]
  3024                              <1> 		   ; AL = lock value (0 or process number)
  3025                              <1> 		   ; AH = open count 
  3026 00005C11 20E4                <1> 	and 	ah, ah
  3027 00005C13 7514                <1> 	jnz	short ctty_ret
  3028                              <1>   	; 12/02/2022
  3029 00005C15 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3030 00005C18 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3031                              <1> 	; iclose (dl=1 or dl=2)
  3032 00005C1A C705[AB700000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3032 00005C22 0000                <1>
  3033                              <1> 			; device not open ! error
  3034                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3035 00005C24 E9AADEFFFF          <1> 	jmp	error
  3036                              <1> 	; 26/01/2014
  3037                              <1> ctty_ret:
  3038 00005C29 FECC                <1> 	dec 	ah ; decrease open count
  3039 00005C2B 7502                <1> 	jnz	short ctty_1
  3040 00005C2D 30C0                <1> 	xor	al, al ; unlock/free tty
  3041                              <1> ctty_1:
  3042 00005C2F 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3043                              <1> 	;
  3044 00005C32 BB[8C700000]        <1> 	mov	ebx, u.ttyp
  3045                              <1> 	;test	dl, 1 ; open for write sign
  3046                              <1> 	;jz	short ctty_2
  3047                              <1> 	; 25/02/2022
  3048 00005C37 F6C202              <1> 	test	dl, 2 ; open for read sign
  3049 00005C3A 7501                <1> 	jnz	short ctty_2
  3050 00005C3C 43                  <1> 	inc	ebx
  3051                              <1> ctty_2:
  3052 00005C3D FEC6                <1> 	inc	dh ; tty number + 1
  3053 00005C3F 3A33                <1> 	cmp	dh, [ebx]
  3054                              <1> 	;jne	short cret
  3055 00005C41 7503                <1> 	jne	short ctty_3 ; 12/02/2022
  3056                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3057 00005C43 C60300              <1> 	mov	byte [ebx], 0
  3058                              <1> ctty_3:
  3059                              <1> 	; 12/02/2022
  3060 00005C46 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3061 00005C48 7401                <1> 	jz	short ctty_4
  3062                              <1> cret:
  3063                              <1> 	;pop	ax
  3064                              <1> 	; 05/02/2022
  3065 00005C4A 58                  <1> 	pop	eax
  3066                              <1> ctty_stc_retn:	; 12/02/2022
  3067                              <1> ctty_4:
  3068 00005C4B C3                  <1> 	retn
  3069                              <1> 
  3070                              <1> ;ctty_err: ; 13/01/2014
  3071                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3072                              <1> ;	jnz	error
  3073                              <1> ;	stc
  3074                              <1> ;	retn
  3075                              <1> 
  3076                              <1> 	; Original UNIX v1 'ctty' routine:
  3077                              <1> 	;	
  3078                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3079                              <1> 	;		;/ point r5 to the console tty buffer
  3080                              <1>         ;decb   (r5) / dec number of processes using console tty
  3081                              <1>         ;br     sret / return via sret
  3082                              <1> 
  3083                              <1> ;ccvt:	; < close tty >
  3084                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3085                              <1> 	;
  3086                              <1> 	; Retro UNIX 8086 v1 modification !
  3087                              <1> 	; 
  3088                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3089                              <1> 	;		(exactly different than this one)
  3090                              <1> 	;	was in 'u9.s' file.
  3091                              <1> 	;
  3092                              <1> 	; DL = 2 -> it is open for reading
  3093                              <1> 	; DL = 1 -> it is open for writing
  3094                              <1> 	;
  3095                              <1> 	; 17/09/2013
  3096                              <1> 	;sub 	al, 10
  3097                              <1> 	;cmp	al, 7
  3098                              <1> 	;jna	short cttyp
  3099                              <1> 	; 13/01/2014
  3100                              <1> 	;jmp	short cttyp
  3101                              <1> 
  3102                              <1> ;cppt: / close paper tape
  3103                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3104                              <1> ;1:
  3105                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3106                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3107                              <1> ;                          / and assign to free list
  3108                              <1> ;               br sret
  3109                              <1> ;        br     1b
  3110                              <1> 
  3111                              <1> ;ejec:	
  3112                              <1> ;	jmp	error
  3113                              <1> ;/ejec:
  3114                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3115                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3116                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3117                              <1> ;/       br     sret / return to caller via 'sret'
  3118                              <1> 
  3119                              <1> ejec:
  3120                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kewrnel v0.2.0.20)
  3121                              <1> 	;	     - Printer Initialization
  3122                              <1> lpt_init:	
  3123                              <1> 	; Ref: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985
  3124                              <1> 	;
  3125                              <1> 	; Default printer port: 378h ; LPT1
  3126                              <1> 	
  3127 00005C4C B401                <1>  	mov	ah, 1  ; INITIALIZE THE PRINTER PORT
  3128                              <1> 	;call	int17h
  3129 00005C4E E8C3FAFFFF          <1> 	call	PRNOP
  3130 00005C53 7414                <1> 	jz	short lpt_init_ok
  3131                              <1> 	
  3132                              <1> 	; replace error code with 'device not ready' error
  3133                              <1> 	; (this may be better for 'sysopen')
  3134 00005C55 B80F000000          <1> 	mov	eax, ERR_PRN_NOT_RDY
  3135 00005C5A A3[AB700000]        <1> 	mov	[u.error], eax
  3136                              <1> 	;jmp	sysret ; (may be) ? ([u.r0] = file descriptor)
  3137 00005C5F A3[5C700000]        <1> 	mov	[u.r0], eax
  3138 00005C64 E96ADEFFFF          <1> 	jmp	error ; (better)	
  3139                              <1> 	
  3140                              <1> lpt_init_ok:
  3141                              <1> 	;jmp	short cret
  3142 00005C69 58                  <1> 	pop	eax    ; inode number
  3143 00005C6A C3                  <1> 	retn
  3144                              <1> 	
  2055                                  %include 'u8.s'        ; 11/06/2015
  2056                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS8.INC
  2057                              <1> ; Last Modification: 12/02/2022
  2058                              <1> ; ----------------------------------------------------------------------------
  2059                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2060                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2061                              <1> ;
  2062                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2063                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2064                              <1> ; <Bell Laboratories (17/3/1972)>
  2065                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2066                              <1> ;
  2067                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2068                              <1> ;
  2069                              <1> ; ****************************************************************************
  2070                              <1> ; 24/10/2015
  2071                              <1> 
  2072                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2073                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2074                              <1> ;; Word 1, byte 0 = device id
  2075                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2076                              <1> ;;          bit 9 = write bit
  2077                              <1> ;;	    bit 10 = read bit	  
  2078                              <1> ;;	    bit 12 = waiting to write bit	
  2079                              <1> ;;	    bit 13 = waiting to read bit
  2080                              <1> ;;	    bit 15 = inhibit bit
  2081                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2082                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2083                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2084                              <1> ;;
  2085                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2086                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2087                              <1> ;;
  2088                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2089                              <1> ;; Word 1, Byte 0 = device id
  2090                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2091                              <1> ;;          bit 9 = write bit
  2092                              <1> ;;	    bit 10 = read bit	  
  2093                              <1> ;;	    bit 12 = waiting to write bit	
  2094                              <1> ;;	    bit 13 = waiting to read bit
  2095                              <1> ;;	    bit 15 = inhibit bit
  2096                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2097                              <1> ;;
  2098                              <1> ;; Original UNIX v1 ->
  2099                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2100                              <1> ;; Original UNIX v1 -> 
  2101                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2102                              <1> ;;
  2103                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2104                              <1> ;;
  2105                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2106                              <1> ;;          0 = fd0
  2107                              <1> ;;	    1 = fd1
  2108                              <1> ;;	    2 = hd0
  2109                              <1> ;;	    3 = hd1
  2110                              <1> ;;	    4 = hd2
  2111                              <1> ;;	    5 = hd3
  2112                              <1> 
  2113                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2114                              <1> 
  2115                              <1> 	; 04/02/2022
  2116                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2117                              <1> 	; 26/04/2013
  2118                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2119                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2120                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2121                              <1> 
  2122                              <1> 	; 04/02/2022
  2123                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2124                              <1> 	; 26/04/2013
  2125                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2126                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2127                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2128                              <1> 
  2129                              <1> bread: 
  2130                              <1> 	; 12/02/2022
  2131                              <1> 	; 04/02/2022
  2132                              <1> 	; 14/07/2015
  2133                              <1> 	; 10/07/2015
  2134                              <1> 	; 09/06/2015
  2135                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2136                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2137                              <1> 	;	
  2138                              <1> 	; / read a block from a block structured device
  2139                              <1> 	;
  2140                              <1> 	; INPUTS ->
  2141                              <1> 	;    [u.fofp] points to the block number
  2142                              <1> 	;    CX = maximum block number allowed on device
  2143                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2144                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2145                              <1> 	;    [u.count]	number of bytes to read in
  2146                              <1> 	; OUTPUTS ->
  2147                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2148                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2149                              <1> 	;
  2150                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2151                              <1> 	;
  2152                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2153                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2154                              <1> 	;	is increased by 1. For example: If user/program request 
  2155                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2156                              <1> 	;  	the next block number just as 512 byte reading is done.
  2157                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2158                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2159                              <1> 	;       enough to keep byte position/offset of the disk), this
  2160                              <1> 	;	defect will not be corrected, user/program must request
  2161                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2162                              <1> 	;       for achieving correct result. In future version(s), 
  2163                              <1> 	;	this defect will be corrected by using different 
  2164                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2165                              <1> 
  2166                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2167                              <1> 			       ; / (only works on tape)
  2168                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2169                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2170                              <1> ;1:
  2171                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2172                              <1> 			    ; / maximum block # allowed on device
  2173                              <1> 		; jnb short @f
  2174                              <1> 		; bhis	1f / yes, 1f (error)
  2175                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2176                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2177                              <1> 		; mov (sp)+,r1 / return block # to r1
  2178                              <1> 		; inc r1 / bump block # to next consecutive block
  2179                              <1> 		; dec (sp) / "2-1-cold" on stack
  2180                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2181                              <1> ;1:
  2182                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2183                              <1> 	;push	ecx ; **
  2184                              <1> 	;26/04/2013
  2185                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2186 00005C6B 2C03                <1> 	sub	al, 3
  2187                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2188 00005C6D A2[BE700000]        <1> 	mov	[u.brwdev], al
  2189                              <1> 	; 09/06/2015
  2190                              <1> 	;movzx	ebx, al
  2191                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2192                              <1> 	; 04/02/2022 (BugFix)
  2193 00005C72 C0E002              <1> 	shl	al, 2 ; * 4
  2194 00005C75 8B88[BE670000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2195                              <1> bread_0:
  2196 00005C7B 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2197                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2198                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2199 00005C7C 8B1D[6C700000]      <1> 	mov	ebx, [u.fofp]
  2200 00005C82 8B03                <1> 	mov	eax, [ebx]
  2201 00005C84 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2202                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2203                              <1> 			       ; / block #
  2204 00005C87 39C8                <1> 	cmp	eax, ecx
  2205                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2206                              <1>        	                     ; / block number allowed
  2207                              <1> 	;jnb	error 	     ; 18/04/2013
  2208                              <1> 		; bhis error10 / yes, error
  2209                              <1> 	; 12/02/2022
  2210                              <1> 	;jb	short bread_1
  2211                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2212                              <1> 	;jmp	error
  2213 00005C89 735A                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2214                              <1> bread_1:
  2215                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2216                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2217                              <1> 	; eAX = Block number (zero based)
  2218                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2219                              <1> preread: ;; call preread
  2220 00005C8B BF[BE700000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2221 00005C90 E888020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2222                              <1> 	;; jc 	error
  2223                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2224                              <1>         ; eAX = Block/Sector number (r1)
  2225                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2226                              <1> 	; 14/03/2013
  2227 00005C95 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2228                              <1>        		; br 1f / branch if block already in a I/O buffer
  2229 00005C97 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2230                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2231 00005C9C E8DA010000          <1> 	call	poke
  2232                              <1>         	; jsr r0,poke / perform the read
  2233                              <1> 	;;jc	error ;2 0/07/2013
  2234                              <1> ; 1:
  2235                              <1>  		; clr *$ps / ps = 0
  2236                              <1>         	; rts r0
  2237                              <1> 	; 12/02/2022
  2238 00005CA1 7305                <1> 	jnc	short bread_2
  2239 00005CA3 E937010000          <1> 	jmp	dskrd_err
  2240                              <1> 
  2241                              <1> ;; return from preread
  2242                              <1> bread_2:
  2243 00005CA8 66810B0040          <1> 	or	word [ebx], 4000h 
  2244                              <1> 		; bis $40000,(r5) 
  2245                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2246                              <1> bread_3: ; 1:
  2247 00005CAD 66F7030024          <1> 	test	word [ebx], 2400h
  2248                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2249 00005CB2 7407                <1> 	jz	short bread_4
  2250                              <1> 		; beq 1f / no
  2251                              <1> 		; cmp cdev,$1 / disk or drum?
  2252                              <1> 		; ble 2f / yes
  2253                              <1> 		; tstb uquant / is the time quantum = 0?
  2254                              <1> 		; bne 2f / no, 2f
  2255                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2256                              <1> 		; jsr r0,sleep; 31. 
  2257                              <1> 			; / put process to sleep in channel 31 (tape)
  2258                              <1> 		; mov (sp)+,r5 / restore r5
  2259                              <1> 		; br 1b / go back
  2260                              <1> ; 2: / drum or disk
  2261                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2262 00005CB4 E8C2F2FFFF          <1> 	call	idle
  2263                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2264 00005CB9 EBF2                <1> 	jmp	short bread_3
  2265                              <1>        		; br 1b
  2266                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2267 00005CBB 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2268                              <1> 		; bic $40000,(r5) / clear bit 14
  2269                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2270 00005CC0 83C308              <1> 	add	ebx, 8
  2271                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2272                              <1> 	; 09/06/2015
  2273 00005CC3 66833D[BB700000]00  <1> 	cmp	word [u.pcount], 0
  2274 00005CCB 7705                <1> 	ja	short bread_5
  2275 00005CCD E880F8FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2276                              <1> bread_5:
  2277                              <1> 	; eBX = system (I/O) buffer address
  2278 00005CD2 E870000000          <1> 	call	dioreg
  2279                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2280                              <1> 	; esi = start address of the transfer (in the buffer)
  2281                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2282                              <1> 	; ecx = transfer count (in bytes)
  2283                              <1> 	;
  2284                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2285                              <1> ;   / of users data
  2286 00005CD7 F3A4                <1> 	rep	movsb
  2287                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2288                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2289                              <1>        		; bne 1b
  2290 00005CD9 59                  <1> 	pop	ecx ; **
  2291 00005CDA 833D[80700000]00    <1> 	cmp	dword [u.count], 0
  2292                              <1> 		; tst u.count / done
  2293 00005CE1 7798                <1> 	ja	short bread_0 ; 09/06/2015
  2294                              <1>        		; beq 1f / yes, return
  2295                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2296                              <1>        		; br bread / read some more
  2297                              <1> ; 1:
  2298 00005CE3 58                  <1> 	pop	eax ; ****
  2299                              <1>        		; mov (sp)+,r0
  2300 00005CE4 C3                  <1>         retn		; 09/06/2015
  2301                              <1> 	;jmp	ret_ 
  2302                              <1> 		;jmp ret / jump to routine that called readi
  2303                              <1> 
  2304                              <1> 	; 08/02/2022
  2305                              <1> brw_oov_err:
  2306 00005CE5 C705[AB700000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2306 00005CED 0000                <1>
  2307 00005CEF E9DFDDFFFF          <1> 	jmp	error
  2308                              <1> 
  2309                              <1> 	; 12/02/2022
  2310                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2311                              <1> 	; 26/04/2013
  2312                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2313                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2314                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2315                              <1> 
  2316                              <1> 	; 12/02/2022				
  2317                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2318                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2319                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2320                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2321                              <1> 
  2322                              <1> bwrite: 
  2323                              <1> 	; 12/02/2022
  2324                              <1> 	; 04/02/2022
  2325                              <1> 	; 14/07/2015
  2326                              <1> 	; 10/07/2015
  2327                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2328                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2329                              <1> 	;	
  2330                              <1> 	;; / write on block structured device
  2331                              <1> 	;
  2332                              <1> 	; INPUTS ->
  2333                              <1> 	;    [u.fofp] points to the block number
  2334                              <1> 	;    CX = maximum block number allowed on device
  2335                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2336                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2337                              <1> 	;    [u.count]	number of bytes to user desires to write
  2338                              <1> 	; OUTPUTS ->
  2339                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2340                              <1> 	;
  2341                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2342                              <1> 	;
  2343                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2344                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2345                              <1> 	;	is increased by 1. For example: If user/program request 
  2346                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2347                              <1> 	;  	the next block number just as 512 byte writing is done.
  2348                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2349                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2350                              <1> 	;       enough to keep byte position/offset of the disk), this
  2351                              <1> 	;	defect will not be corrected, user/program must request
  2352                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2353                              <1> 	;       for achieving correct result. In future version(s), 
  2354                              <1> 	;	this defect will be corrected by using different 
  2355                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2356                              <1> 
  2357                              <1>        		; jsr r0,tstdeve / test the device for an error
  2358                              <1> 	;push	ecx ; **
  2359                              <1> 	;26/04/2013
  2360                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2361 00005CF4 2C03                <1> 	sub	al, 3
  2362                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2363 00005CF6 A2[BE700000]        <1> 	mov	[u.brwdev], al
  2364                              <1> 	; 09/06/2015
  2365                              <1> 	;movzx	ebx, al
  2366                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2367                              <1> 	; 04/02/2022 (BugFix)
  2368 00005CFB C0E002              <1> 	shl	al, 2 ; * 4
  2369 00005CFE 8B88[BE670000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2370                              <1> bwrite_0:
  2371 00005D04 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2372                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2373                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2374 00005D05 8B1D[6C700000]      <1> 	mov	ebx, [u.fofp]
  2375 00005D0B 8B03                <1> 	mov	eax, [ebx]       
  2376 00005D0D C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2377                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2378 00005D10 39C8                <1> 	cmp	eax, ecx
  2379                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2380                              <1>        	                     ; / block number allowed
  2381                              <1> 	;jnb	error	     ; 18/04/2013
  2382                              <1> 		; bhis error10 / yes, error
  2383                              <1>      	; 12/02/2022
  2384                              <1> 	;jb	short bwrite_1
  2385                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2386                              <1> 	;jmp	error
  2387 00005D12 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2388                              <1> bwrite_1:
  2389                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2390                              <1> 		; inc *u.fofp / no, increment block number
  2391                              <1> 	; 09/06/2015 - 10/07/2015
  2392 00005D14 66833D[BB700000]00  <1> 	cmp	word [u.pcount], 0
  2393 00005D1C 7705                <1> 	ja	short bwrite_2
  2394 00005D1E E82BF8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2395                              <1> bwrite_2:
  2396 00005D23 BF[BE700000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2397 00005D28 E8D3000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2398                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2399                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2400 00005D2D E815000000          <1>         call	dioreg
  2401                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2402                              <1> 	; esi =  destination address (in the buffer)
  2403                              <1> 	; edi =  [u.pbase], start address of transfer in user's memory space
  2404                              <1> 	; ecx =  transfer count (in bytes)
  2405                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2406 00005D32 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2407 00005D34 F3A4                <1> 	rep	movsb
  2408                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2409                              <1>        		; dec r3 / area to the I/O buffer
  2410                              <1>        		; bne 1b
  2411 00005D36 E80D010000          <1> 	call	dskwr
  2412                              <1> 		; jsr r0,dskwr / write it out on the device
  2413 00005D3B 59                  <1> 	pop	ecx ; **
  2414 00005D3C 833D[80700000]00    <1>         cmp     dword [u.count], 0
  2415                              <1> 		; tst u.count / done
  2416 00005D43 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2417                              <1> 		; beq 1f / yes, 1f
  2418                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2419                              <1>        		; br bwrite / go back and write next block
  2420                              <1> ; 1:
  2421 00005D45 58                  <1> 	pop	eax ; ****
  2422                              <1>        		; mov (sp)+,r0
  2423 00005D46 C3                  <1> 	retn		; 09/06/2015
  2424                              <1>         ;jmp	ret_ 
  2425                              <1> 		; jmp ret / return to routine that called writei
  2426                              <1> ;error10:
  2427                              <1> ;       jmp     error  ; / see 'error' routine
  2428                              <1> 
  2429                              <1> dioreg:
  2430                              <1> 	; 04/02/2022
  2431                              <1> 	; 14/07/2015
  2432                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2433                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2434                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2435                              <1> 	;	
  2436                              <1> 	; bookkeeping on block transfers of data
  2437                              <1> 	;
  2438                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2439                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2440                              <1> 	; 10/07/2015
  2441                              <1> 	; * returns byte offset from beginning of current sector buffer
  2442                              <1> 	; (beginning of data) in ESI
  2443                              <1> 	;
  2444 00005D47 8B0D[80700000]      <1> 	mov	ecx, [u.count]
  2445                              <1> 		; mov u.count,r3 / move char count to r3
  2446                              <1>         ; 04/02/2022
  2447 00005D4D 31D2                <1> 	xor	edx, edx
  2448 00005D4F B602                <1> 	mov	dh, 2
  2449                              <1> 	; edx = 512
  2450 00005D51 39D1                <1> 	cmp	ecx, edx ; 512
  2451                              <1> 	;cmp 	ecx, 512
  2452                              <1> 		; cmp r3,$512. / more than 512. char?
  2453 00005D53 7602                <1> 	jna	short dioreg_0
  2454                              <1> 		; blos 1f / no, branch
  2455 00005D55 89D1                <1> 	mov	ecx, edx ; 512
  2456                              <1> 	;mov	ecx, 512
  2457                              <1> 		; mov $512.,r3 / yes, just take 512.
  2458                              <1> dioreg_0:
  2459                              <1> 	; 09/06/2015
  2460 00005D57 663B0D[BB700000]    <1> 	cmp	cx, [u.pcount]
  2461 00005D5E 7607                <1> 	jna	short dioreg_1
  2462 00005D60 668B0D[BB700000]    <1> 	mov	cx, [u.pcount]
  2463                              <1> dioreg_1:
  2464                              <1> ; 1:
  2465 00005D67 8B15[7C700000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2466                              <1> 	        ; mov u.base,r2 / put users base in r2
  2467 00005D6D 010D[84700000]      <1> 	add	[u.nread], ecx
  2468                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2469 00005D73 290D[80700000]      <1> 	sub	[u.count], ecx
  2470                              <1> 		; sub r3,u.count / update count
  2471 00005D79 010D[7C700000]      <1> 	add	[u.base], ecx
  2472                              <1> 		; add r3,u.base / update base
  2473                              <1> 	; 10/07/2015
  2474                              <1> 	; Retro UNIX 386 v1 - modification !
  2475                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2476                              <1> 	; (It will point to next byte position instead of next block no.)
  2477 00005D7F 8B35[6C700000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2478 00005D85 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2479 00005D87 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2480 00005D89 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2481 00005D8E 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2482 00005D90 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2483                              <1> 	; 09/06/2015 - 10/07/2015
  2484 00005D92 66290D[BB700000]    <1> 	sub	[u.pcount], cx
  2485 00005D99 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2486 00005D9F 8B3D[B7700000]      <1> 	mov	edi, [u.pbase]
  2487 00005DA5 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2488 00005DAB 01D7                <1> 	add	edi, edx
  2489 00005DAD 893D[B7700000]      <1> 	mov	[u.pbase], edi
  2490 00005DB3 010D[B7700000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2491 00005DB9 C3                  <1> 	retn
  2492                              <1> 		; rts r0 / return
  2493                              <1> 
  2494                              <1> dskrd:
  2495                              <1> 	; 12/02/2022
  2496                              <1> 	; 18/08/2015
  2497                              <1> 	; 02/07/2015
  2498                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2499                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2500                              <1> 	;
  2501                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2502                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2503                              <1> 	; (number specified in r1) in the acquired buffer.
  2504                              <1> 	; If the device is busy at the time dskrd is called,	
  2505                              <1> 	; dskrd calls idle.
  2506                              <1> 	; 
  2507                              <1> 	; INPUTS ->
  2508                              <1> 	;    r1 - block number
  2509                              <1> 	;    cdev - current device number 
  2510                              <1> 	; OUTPUTS ->
  2511                              <1> 	;    r5 - points to first data word in I/O buffer
  2512                              <1> 	;
  2513                              <1> 	; ((AX = R1)) input/output
  2514                              <1> 	; ((BX = R5)) output 
  2515                              <1> 	;
  2516                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2517                              <1> 	;
  2518 00005DBA E851010000          <1> 	call 	bufaloc
  2519                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2520                              <1> 			       ; / get a free I/O buffer
  2521                              <1> 	;;jc	error ; 20/07/2013
  2522 00005DBF 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2523                              <1>        		; br 1f / branch if block already in a I/O buffer
  2524                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2525 00005DC1 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2526                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2527                              <1> 		               ; / I/O queue entry for buffer
  2528 00005DC6 E8B0000000          <1> 	call	poke
  2529                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2530                              <1> 			    ; /	bit 10=1 says read
  2531                              <1> 	; 09/06/2015
  2532                              <1> 	;jnc	short dskrd_1
  2533                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2534                              <1> 	;jmp	error
  2535                              <1> 	; 08/02/2022
  2536 00005DCB 7212                <1> 	jc	short dskrd_3
  2537                              <1> dskrd_1: ; 1:
  2538                              <1>        		;clr *$ps
  2539 00005DCD 66F7030024          <1>        	test	word [ebx], 2400h
  2540                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2541                              <1> 				; / jump to idle
  2542 00005DD2 7407                <1>        	jz	short dskrd_2
  2543                              <1> 		; beq 1f
  2544                              <1>         ;;mov   ecx, [s.wait_]
  2545 00005DD4 E8A2F1FFFF          <1>        	call	idle
  2546                              <1> 		; jsr r0,idle; s.wait+2
  2547 00005DD9 EBF2                <1> 	jmp 	short dskrd_1
  2548                              <1>        		; br 1b
  2549                              <1> dskrd_2: ; 1:
  2550 00005DDB 83C308              <1>         add	ebx, 8
  2551                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2552                              <1> 			  ; / just read in
  2553 00005DDE C3                  <1>        	retn
  2554                              <1> 		; rts r0
  2555                              <1> dskrd_err: 
  2556                              <1> 	; 08/02/2022
  2557                              <1> 	; (jump from 'bread' error)
  2558                              <1> dskrd_3:	
  2559                              <1> 	; 08/02/2022
  2560 00005DDF 803D[BE700000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2561 00005DE6 7509                <1> 	jne	short dskrd_4 ; no
  2562                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2563 00005DE8 C605[BE700000]00    <1> 	mov	byte [u.brwdev], 0
  2564 00005DEF EB0A                <1> 	jmp	short dskrd_5
  2565                              <1> dskrd_4:
  2566 00005DF1 C705[AB700000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2566 00005DF9 0000                <1>
  2567                              <1> dskrd_5:
  2568 00005DFB E9D3DCFFFF          <1> 	jmp	error
  2569                              <1> 
  2570                              <1> bwslot:
  2571                              <1> 	; 04/02/2022
  2572                              <1> 	; 10/07/2015
  2573                              <1> 	;	If the block/sector is not placed in a buffer
  2574                              <1> 	;	before 'wslot', it must be read before
  2575                              <1> 	;	it is written! (Otherwise transfer counts less
  2576                              <1> 	;	than 512 bytes will be able to destroy existing 
  2577                              <1> 	;	data on disk.)
  2578                              <1> 	;
  2579                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2580                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2581                              <1> 	; Retro UNIX 8086 v1 modification !
  2582                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2583                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2584                              <1> 	;	-> eAX = block number
  2585                              <1> 	;
  2586 00005E00 E818010000          <1> 	call	bufaloc_0
  2587 00005E05 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2588                              <1> 	; 04/02/2022
  2589                              <1> 	; ebx = buffer header address
  2590                              <1> bwslot_0:
  2591                              <1> 	; 10/07/2015
  2592 00005E07 8B35[6C700000]      <1> 	mov	esi, [u.fofp]
  2593 00005E0D 8B06                <1> 	mov	eax, [esi]
  2594 00005E0F 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2595 00005E14 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2596                              <1> 		       ; recent disk data must be placed in the buffer
  2597 00005E16 813D[80700000]0002- <1> 	cmp	dword [u.count], 512
  2597 00005E1E 0000                <1>
  2598 00005E20 730F                <1> 	jnb	short wslot_0	
  2599                              <1> bwslot_1:
  2600 00005E22 E89AFFFFFF          <1> 	call	dskrd_0
  2601                              <1> 	; 04/02/2022
  2602                              <1> 	; ebx = buffer data address = buffer header address + 8
  2603 00005E27 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2604 00005E2A EB05                <1> 	jmp 	short wslot_0
  2605                              <1> 
  2606                              <1> wslot:
  2607                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2608                              <1> 	; 		(32 bit modifications)
  2609                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2610                              <1> 	;
  2611                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2612                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2613                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2614                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2615                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2616                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2617                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2618                              <1> 	;
  2619                              <1> 	; INPUTS ->
  2620                              <1>  	;    r1 - block number
  2621                              <1> 	;    cdev - current (block/disk) device number
  2622                              <1>  	;
  2623                              <1> 	; OUTPUTS ->
  2624                              <1> 	;    bufp - bits 9 and 15 are set, 
  2625                              <1> 	;           the remainder of the word left unchanged
  2626                              <1> 	;    r5 - points to first data word in I/O buffer
  2627                              <1> 	;
  2628                              <1> 	; ((AX = R1)) input/output
  2629                              <1> 	; ((BX = R5)) output 
  2630                              <1> 	;
  2631                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2632                              <1> 
  2633 00005E2C E8DF000000          <1> 	call	bufaloc
  2634                              <1> 	; 10/07/2015
  2635                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2636                              <1>         	; br 1f / word in buffer in r5
  2637                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2638                              <1>         ; eAX = Block/Sector number (r1)
  2639                              <1> wslot_0: ;1:
  2640 00005E31 66F7030024          <1>      	test	word [ebx], 2400h
  2641                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2642                              <1> 				; / of I/O queue entry
  2643 00005E36 7407                <1> 	jz	short wslot_1
  2644                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2645                              <1> 		        ; / or not waiting to read)
  2646                              <1> 
  2647                              <1>         ;;mov	ecx, [s.wait_] ; 29/07/2013
  2648 00005E38 E83EF1FFFF          <1> 	call	idle
  2649                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2650                              <1>        	                     ; / idle
  2651 00005E3D EBF2                <1> 	jmp	short wslot_0
  2652                              <1> 		; br 1b / till finished
  2653                              <1> wslot_1: ;1:
  2654 00005E3F 66810B0082          <1> 	or      word [ebx], 8200h
  2655                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2656                              <1>                             	 ; / (write, inhibit bits)
  2657                              <1>        		; clr *$ps / clear processor status
  2658 00005E44 83C308              <1> 	add	ebx, 8 ; 11/06/2015
  2659                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2660                              <1> 			  ; / for this block
  2661                              <1> dskwr_1:	; 08/02/2022
  2662 00005E47 C3                  <1> 	retn
  2663                              <1> 		; rts r0
  2664                              <1> dskwr:
  2665                              <1> 	; 12/02/2022
  2666                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2667                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2668                              <1> 	;
  2669                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2670                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2671                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2672                              <1> 	; previously has supplied all the information required in the
  2673                              <1> 	; I/O queue entry.
  2674                              <1> 	;
  2675                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2676                              <1> 	;
  2677                              <1> 	;
  2678 00005E48 8B1D[1C700000]      <1> 	mov	ebx, [bufp]
  2679 00005E4E 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2680                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2681                              <1>                                   ; / bottom of queue
  2682 00005E53 E823000000          <1> 	call	poke
  2683                              <1> 	; 09/06/2015
  2684 00005E58 73ED                <1> 	jnc	short dskwr_1
  2685                              <1> 	; 12/02/2022
  2686 00005E5A 803D[BE700000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2687 00005E61 7509                <1> 	jne	short dskwr_0 ; no
  2688                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2689 00005E63 C605[BE700000]00    <1> 	mov	byte [u.brwdev], 0
  2690 00005E6A EB0A                <1> 	jmp	short dskwr_2
  2691                              <1> dskwr_0:
  2692 00005E6C C705[AB700000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2692 00005E74 0000                <1>
  2693                              <1> dskwr_2:
  2694 00005E76 E958DCFFFF          <1> 	jmp	error
  2695                              <1> ;dskwr_1:
  2696                              <1> ;	retn
  2697                              <1> 
  2698                              <1> ;ppoke:
  2699                              <1>        		; mov $340,*$ps
  2700                              <1>        		; jsr r0,poke
  2701                              <1>        		; clr *$ps
  2702                              <1> 		; rts r0
  2703                              <1> poke:
  2704                              <1> 	; 04/02/2022 (32 bit reg push pop)
  2705                              <1> 	; 24/10/2015
  2706                              <1> 	; 20/08/2015
  2707                              <1> 	; 18/08/2015
  2708                              <1> 	; 02/07/2015
  2709                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2710                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2711                              <1> 	;
  2712                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2713                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2714                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2715                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2716                              <1> 	;
  2717                              <1> 	; Basic I/O functions for all block structured devices
  2718                              <1> 	;
  2719                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2720                              <1> 	;
  2721                              <1> 	; 20/07/2013 modifications
  2722                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2723                              <1> 	; INPUTS -> 
  2724                              <1> 	;        (EBX = buffer header address)
  2725                              <1> 	; OUTPUTS ->
  2726                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2727                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2728                              <1> 	;		(drive not ready or r/w error!)
  2729                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2730                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2731                              <1> 	;        (also it indicates invalid buffer data)
  2732                              <1> 	;
  2733 00005E7B 53                  <1> 	push	ebx
  2734                              <1>        		; mov r1,-(sp)
  2735                              <1>        		; mov r2,-(sp)
  2736                              <1>        		; mov r3,-(sp)
  2737 00005E7C 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2738                              <1> 	;
  2739                              <1> 	; 09/06/2015
  2740                              <1> 	; (permit read/write after a disk R/W error)
  2741 00005E7D 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2742 00005E7F B001                <1> 	mov	al, 1
  2743 00005E81 D2E0                <1> 	shl	al, cl
  2744 00005E83 8405[44700000]      <1> 	test 	al, [active] ; busy ? (error)
  2745 00005E89 7408                <1> 	jz	short poke_0
  2746 00005E8B F6D0                <1> 	not	al
  2747 00005E8D 2005[44700000]      <1> 	and	[active], al ; reset busy bit for this device only
  2748                              <1> poke_0:
  2749 00005E93 BE[3C700000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2750                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2751                              <1> 					 ; / I/O queue pointer
  2752                              <1> poke_1: ; 1:
  2753 00005E98 83EE04              <1>         sub	esi, 4
  2754 00005E9B 8B1E                <1> 	mov	ebx, [esi]
  2755                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2756 00005E9D 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2757 00005EA0 F6C406              <1>        	test	ah, 06h
  2758                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2759                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2760                              <1> 			       ; / queue entry
  2761 00005EA3 745C                <1>         jz      short poke_5
  2762                              <1> 		; beq 2f / branch to 2f if both are clear
  2763                              <1> 	; 31/07/2013
  2764                              <1> 	;test	ah, 0B0h ; (*)
  2765                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2766                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2767                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2768                              <1> 		; bne 2f / branch if any are set
  2769                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2770                              <1>     		; movb (r1),r3 / get device id
  2771 00005EA5 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2772                              <1> 	;mov	edi, ecx ; 26/04/2013
  2773 00005EA8 31C0                <1> 	xor 	eax, eax ; 0
  2774                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2775                              <1> 		; tstb deverr(r3) / test for errors on this device
  2776                              <1>        	;jna	short poke_2 
  2777                              <1> 		; beq 3f / branch if no errors
  2778                              <1> 	; 02/07/2015
  2779                              <1> 	;dec	eax
  2780                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2781                              <1>        		; mov $-1,2(r1) / destroy associativity
  2782                              <1> 	;shr	eax, 24
  2783                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2784                              <1> 		; clrb 1(r1) / do not do I/O
  2785                              <1> 	;jmp     short poke_5
  2786                              <1>         ;       ; br 2f
  2787                              <1>                 ; rts r0
  2788                              <1> poke_2: ; 3:
  2789                              <1> 	; 02/07/2015
  2790 00005EAA FEC1                <1> 	inc	cl ; 0FFh -> 0
  2791 00005EAC 7453                <1> 	jz	short poke_5
  2792 00005EAE FEC0                <1> 	inc	al ; mov ax, 1
  2793 00005EB0 FEC9                <1> 	dec	cl
  2794 00005EB2 7402                <1> 	jz	short poke_3
  2795                              <1> 	; 26/04/2013 Modification
  2796                              <1> 	;inc	al ; mov ax, 1
  2797                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2798                              <1> 	;jz	short poke_3 ; cl = 0
  2799 00005EB4 D2E0                <1> 	shl	al, cl ; shl ax, cl
  2800                              <1> poke_3:
  2801                              <1> 	;test	[active], ax
  2802 00005EB6 8405[44700000]      <1> 	test	[active], al
  2803                              <1> 		; bit $2,active / test disk busy bit
  2804 00005EBC 7543                <1> 	jnz     short poke_5
  2805                              <1> 		; bne 2f / branch if bit is set
  2806                              <1> 	;or	[active], ax
  2807 00005EBE 0805[44700000]      <1> 	or	[active], al
  2808                              <1> 		; bis $2,active / set disk busy bit
  2809                              <1> 	;push	ax
  2810                              <1> 	; 04/02/2022
  2811 00005EC4 50                  <1> 	push	eax
  2812 00005EC5 E8C9000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2813                              <1> 	;mov    [edi+drv.error], ah
  2814                              <1> 	; 04/02/2022
  2815 00005ECA 58                  <1> 	pop	eax
  2816                              <1> 	;pop	ax
  2817 00005ECB 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2818                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2819                              <1> 	;jna	short poke_4
  2820                              <1> 		; tstb deverr(r3) / test for errors on this device
  2821                              <1>        		; beq 3f / branch if no errors
  2822                              <1> 	; 02/07/2015 (32 bit modification)
  2823                              <1> 	; 20/07/2013
  2824 00005ECD C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2825                              <1>        		; mov $-1,2(r1) / destroy associativity
  2826 00005ED4 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2827                              <1> 		; clrb 1(r1) / do not do I/O
  2828 00005ED9 EB26                <1> 	jmp     short poke_5
  2829                              <1> poke_4:	; 20/07/2013
  2830                              <1> 	; 17/07/2013
  2831 00005EDB F6D0                <1> 	not 	al 
  2832 00005EDD 2005[44700000]      <1> 	and	[active], al ; reset, not busy
  2833                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2834                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2835 00005EE3 668B03              <1> 	mov	ax, [ebx]
  2836                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2837 00005EE6 66250006            <1>         and	ax, 600h
  2838                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2839 00005EEA 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2840                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2841 00005EEF C0E403              <1> 	shl	ah, 3
  2842                              <1>        		; rol r3
  2843                              <1>                 ; rol r3
  2844                              <1>                 ; rol r3	
  2845 00005EF2 660903              <1> 	or	[ebx], ax
  2846                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2847                              <1> 			   ; bits 12 and 13
  2848 00005EF5 E881F0FFFF          <1> 	call	idle ; 18/01/2014
  2849                              <1> 	;; sti
  2850                              <1> 	;hlt 	; wait for a hardware interrupt
  2851                              <1> 	;; cli
  2852                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2853                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2854                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2855                              <1> 	; method, this procedure will wait for a time according to
  2856                              <1> 	; multi tasking and time sharing concept.
  2857                              <1> 	;
  2858                              <1> 	; 24/10/2015
  2859                              <1> 	;not	ax 
  2860 00005EFA 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2861 00005EFE 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2862                              <1> poke_5: ;2:
  2863 00005F01 81FE[1C700000]      <1>         cmp     esi, bufp
  2864                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  2865                              <1>                             ; / has been scanned
  2866 00005F07 778F                <1> 	ja      short poke_1
  2867                              <1>                ; bhi 1b
  2868                              <1> 	; 24/03/2013
  2869                              <1>        		; mov (sp)+,r3
  2870                              <1>        		; mov (sp)+,r2
  2871                              <1>        		; mov (sp)+,r1
  2872 00005F09 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2873 00005F0A 5B                  <1> 	pop 	ebx
  2874                              <1> 	; 02/07/2015 (32 bit modification)
  2875                              <1> 	; 20/07/2013
  2876                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2877 00005F0B 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2878                              <1> 	;	
  2879                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2880                              <1> 	; or written succesfully; even if an error occurs while
  2881                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2882                              <1> 	;
  2883                              <1> 	; 09/06/2015
  2884 00005F0E F5                  <1> 	cmc
  2885 00005F0F C3                  <1> 	retn
  2886                              <1>                 ; rts r0
  2887                              <1> 
  2888                              <1> bufaloc:
  2889                              <1> 	; 04/02/2022
  2890                              <1> 	; 20/08/2015
  2891                              <1> 	; 19/08/2015
  2892                              <1> 	; 02/07/2015
  2893                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2894                              <1> 	;	     (32 bit modifications)	
  2895                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2896                              <1> 	;
  2897                              <1> 	; bufaloc - Block device I/O buffer allocation
  2898                              <1> 	; 
  2899                              <1> 	; INPUTS ->
  2900                              <1> 	;    r1 - block number
  2901                              <1> 	;    cdev - current (block/disk) device number
  2902                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2903                              <1> 	; OUTPUTS ->
  2904                              <1> 	;    r5 - pointer to buffer allocated
  2905                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2906                              <1> 	;
  2907                              <1> 	; ((AX = R1)) input/output
  2908                              <1> 	; ((BX = R5)) output
  2909                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2910                              <1> 	;    zf=1 -> block already in a I/O buffer
  2911                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2912                              <1> 	;    ((DL = Device ID))
  2913                              <1> 	;    (((DH = 0 or 1)))
  2914                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2915                              <1> 	;    ((CX and DH will not be used after return)))
  2916                              <1> 
  2917                              <1> 	;;push 	esi ; ***
  2918                              <1> 		; mov r2,-(sp) / save r2 on stack
  2919                              <1>        		; mov $340,*$ps / set processor priority to 7
  2920                              <1> 		; 20/07/2013
  2921                              <1> 	; 26/04/2013
  2922                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  2923                              <1> 	;mov	edi, rdev  ; offset mdev = offset rdev + 1
  2924                              <1> 	;add	edi, ebx
  2925                              <1> 	; 09/01/2022
  2926 00005F10 0FB63D[40700000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  2927 00005F17 81C7[42700000]      <1> 	add	edi, rdev
  2928                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2929                              <1> 			;; eDI points to device id.
  2930 00005F1D 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2931                              <1> 	; 11/06/2015
  2932 00005F20 80BB[DA670000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2933 00005F27 720F                <1> 	jb	short bufaloc_9
  2934 00005F29 C705[AB700000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2934 00005F31 0000                <1>
  2935 00005F33 E99BDBFFFF          <1> 	jmp	error
  2936                              <1> bufaloc_9:
  2937 00005F38 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2938                              <1> bufaloc_10: ; 02/07/2015
  2939 00005F3A 31ED                <1> 	xor 	ebp, ebp ; 0
  2940 00005F3C 55                  <1> 	push	ebp ; 0
  2941 00005F3D 89E5                <1>         mov     ebp, esp	
  2942                              <1> 	;
  2943                              <1> bufaloc_1: ;1:
  2944                              <1> 		; clr -(sp) / vacant buffer
  2945 00005F3F BE[1C700000]        <1>         mov 	esi, bufp
  2946                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  2947                              <1> 			     ; / entrys in buffer area
  2948                              <1> bufaloc_2: ;2:
  2949 00005F44 8B1E                <1> 	mov	ebx, [esi]
  2950                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  2951                              <1> 			    ; queue entry into r5
  2952 00005F46 66F70300F6          <1> 	test	word [ebx], 0F600h
  2953                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  2954 00005F4B 7503                <1>         jnz	short bufaloc_3
  2955                              <1> 		; bne 3f / branch when 
  2956                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  2957                              <1>                        ; / (i.e., buffer busy)
  2958 00005F4D 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  2959                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  2960                              <1> 			; / found points to word 2 of I/O queue entry)
  2961                              <1> bufaloc_3: ;3:
  2962                              <1> 	;mov	dl, [edi] ; 26/04/2013
  2963                              <1> 	;
  2964 00005F50 3813                <1> 	cmp	[ebx], dl	
  2965                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  2966                              <1> 			       ; / as current device
  2967 00005F52 7508                <1> 	jne	short bufaloc_4
  2968                              <1>        		; bne 3f
  2969 00005F54 394304              <1> 	cmp	[ebx+4], eax
  2970                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  2971                              <1> 			     ; / same as current block number
  2972 00005F57 7503                <1>        	jne	short bufaloc_4
  2973                              <1> 		; bne 3f
  2974                              <1> 	;add	esp, 4
  2975 00005F59 59                  <1> 	pop	ecx
  2976                              <1>        		; tst (sp)+ / bump stack pointer
  2977 00005F5A EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  2978                              <1> 				; jump to bufaloc_6 in original Unix v1
  2979                              <1>        		; br 1f / use this buffer
  2980                              <1> bufaloc_4: ;3:
  2981 00005F5C 83C604              <1> 	add	esi, 4 ; 20/08/2015
  2982                              <1> 	;
  2983 00005F5F 81FE[34700000]      <1> 	cmp	esi, bufp + (nbuf*4)
  2984                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  2985 00005F65 72DD                <1> 	jb	short bufaloc_2
  2986                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  2987                              <1>                        ; / buffers not checked)
  2988 00005F67 5E                  <1>         pop	esi
  2989                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  2990                              <1> 			     ; / to last free block
  2991 00005F68 09F6                <1>        	or	esi, esi 
  2992 00005F6A 7507                <1> 	jnz	short bufaloc_5
  2993                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  2994                              <1> 	        ; / if a free buffer is found branch to 2f
  2995                              <1>         ;; mov  ecx, [s.wait_]
  2996 00005F6C E80AF0FFFF          <1> 	call	idle
  2997                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  2998 00005F71 EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  2999                              <1>        		; br 1b
  3000                              <1> bufaloc_5: ;2:
  3001                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3002 00005F73 FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  3003                              <1> bufaloc_6: ;1:
  3004 00005F75 8B1E                <1>         mov    	ebx, [esi] 
  3005                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3006                              <1> 			     ; / entry in r5
  3007                              <1> 	;; 26/04/2013
  3008                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3009 00005F77 8813                <1> 	mov 	[ebx], dl
  3010                              <1> 		; movb cdev,(r5) / put current device number 
  3011                              <1> 				 ; / in I/O queue entry
  3012 00005F79 894304              <1> 	mov 	[ebx+4], eax
  3013                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3014                              <1> 			     ; / of I/O queue entry
  3015                              <1> bufaloc_7: ;1:
  3016 00005F7C 81FE[1C700000]      <1>         cmp	esi, bufp
  3017                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3018                              <1> 			     ; / and put latest assigned
  3019 00005F82 760A                <1> 	jna	short bufaloc_8	
  3020                              <1>        		; blos 1f / buffer on the top 
  3021                              <1> 			; / (this makes if the lowest priority)
  3022 00005F84 83EE04              <1> 	sub	esi, 4
  3023 00005F87 8B0E                <1> 	mov	ecx, [esi]
  3024 00005F89 894E04              <1> 	mov	[esi+4], ecx
  3025                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3026 00005F8C EBEE                <1> 	jmp 	short bufaloc_7        
  3027                              <1> 		; br 1b
  3028                              <1> bufaloc_8: ;1:
  3029 00005F8E 891E                <1>         mov	[esi], ebx
  3030                              <1> 		; mov r5,(r2)
  3031                              <1> 	;;pop	esi ; ***
  3032                              <1>        		; mov (sp)+,r2 / restore r2
  3033 00005F90 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3034                              <1> 		; Retro UNIX 8086 v1 modification
  3035                              <1> 		; zf=1 --> block already is in an I/O buffer
  3036                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3037 00005F92 C3                  <1> 	retn
  3038                              <1> 		; rts r0
  3039                              <1> 
  3040                              <1> diskio:
  3041                              <1> 	; 12/02/2022
  3042                              <1> 	; 04/02/2022 (Retro UNIX 386 v1 2022, Kernel v0.2.0.18)
  3043                              <1> 	; 10/07/2015
  3044                              <1> 	; 02/07/2015
  3045                              <1> 	; 16/06/2015
  3046                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3047                              <1> 	;	     (80386 protected mode modifications)	
  3048                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3049                              <1> 	;
  3050                              <1> 	; Retro UNIX 8086 v1 feature only !
  3051                              <1> 	;
  3052                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3053                              <1> 	; 04/07/2009 - 20/07/2011
  3054                              <1> 	;
  3055                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3056                              <1> 	;
  3057                              <1>         ; INPUTS ->
  3058                              <1> 	; 	   eBX = System I/O Buffer header address
  3059                              <1> 	;
  3060                              <1>         ; OUTPUTS -> cf=0 --> done 
  3061                              <1> 	; 	     cf=1 --> error code in AH
  3062                              <1> 	;
  3063                              <1> 	; (Modified registers: eAX, eCX, eDX)
  3064                              <1> 	
  3065                              <1> ;rw_disk_sector:
  3066                              <1> 	; 12/02/2022
  3067                              <1> 	; 10/07/2015
  3068                              <1> 	; 02/07/2015
  3069                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3070                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3071                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3072                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3073                              <1> 	;
  3074                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  3075 00005F93 B602                <1> 	mov	dh, 2
  3076 00005F95 668B03              <1> 	mov	ax, [ebx] 
  3077                              <1> 	;
  3078 00005F98 56                  <1> 	push	esi ; ****
  3079 00005F99 53                  <1> 	push	ebx ; ***
  3080                              <1> 	;
  3081 00005F9A 0FB6C8              <1> 	movzx	ecx, al
  3082 00005F9D 89CE                <1> 	mov	esi, ecx
  3083                              <1> 	;
  3084 00005F9F 38F1                <1> 	cmp	cl, dh ; 2
  3085 00005FA1 7202                <1> 	jb	short rwdsk0
  3086 00005FA3 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3087                              <1> rwdsk0:
  3088 00005FA5 A2[8B670000]        <1> 	mov	[drv], al
  3089 00005FAA 81C6[DA670000]      <1> 	add	esi, drv.status
  3090                              <1> 	; 11/06/2015
  3091 00005FB0 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3092 00005FB3 7204                <1> 	jb      short rwdsk1
  3093                              <1> 	; 'drive not ready' error
  3094                              <1> 	; 12/02/2022
  3095                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3096                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3097                              <1> 	;;jmp	error
  3098                              <1> 	;stc	; cf = 1
  3099                              <1> 	;retn
  3100                              <1> 	; 12/02/2022
  3101 00005FB5 B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3102 00005FB7 EB20                <1> 	jmp	short rwdsk_err1
  3103                              <1> rwdsk1:
  3104 00005FB9 F6C402              <1> 	test	ah, 2
  3105                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  3106                              <1> 			 ; write bit
  3107 00005FBC 7402                <1> 	jz	short rwdsk2
  3108                              <1> 	;test	ah, 4
  3109                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3110                              <1> 	;		 ; read bit
  3111                              <1> 	;jz	short diskio_ret
  3112 00005FBE FEC6                <1> 	inc	dh ; 03h = write
  3113                              <1> rwdsk2:
  3114 00005FC0 88C2                <1> 	mov	dl, al
  3115 00005FC2 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3116 00005FC5 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3117 00005FC7 C0E102              <1> 	shl	cl, 2
  3118 00005FCA 81C1[BE670000]      <1> 	add	ecx, drv.size ; disk size
  3119 00005FD0 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3120 00005FD2 7214                <1> 	jb      short rwdsk3
  3121                              <1>  	; 'out of volume' error
  3122                              <1> 	; 12/02/2022
  3123                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3124                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3125                              <1> 	;;jmp	error
  3126                              <1> 	;stc	; cf = 1
  3127                              <1> 	;retn
  3128                              <1> 	; 12/02/2022
  3129 00005FD4 B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3130                              <1> rwdsk_err1:
  3131 00005FD9 C605[BE700000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3132 00005FE0 890D[AB700000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3133 00005FE6 EB30                <1> 	jmp	short rwdsk_err2
  3134                              <1> rwdsk3:
  3135                              <1> 	; 11/06/2015
  3136 00005FE8 83C304              <1> 	add	ebx, 4 ; buffer address
  3137 00005FEB C605[DA700000]04    <1> 	mov	byte [retry_count], 4
  3138 00005FF2 F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3139 00005FF5 7432                <1>         jz      short rwdsk_chs
  3140                              <1> rwdsk_lba:
  3141                              <1> 	; LBA read/write (with private LBA function) 
  3142                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3143 00005FF7 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3144 00005FFA 89C1                <1> 	mov	ecx, eax ; sector number
  3145                              <1> 	; ebx = buffer (data) address
  3146                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3147                              <1> rwdsk_lba_retry:
  3148                              <1> 	;mov	dl, [drv]
  3149                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3150 00005FFC B419                <1> 	mov	ah, 1Ch - 3h ; LBA write function number - 3
  3151 00005FFE 00F4                <1> 	add	ah, dh		
  3152 00006000 B001                <1> 	mov	al, 1
  3153                              <1> 	;int	13h
  3154 00006002 E8AAC5FFFF          <1> 	call	int13h
  3155 00006007 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3156 00006009 730E                <1> 	jnc	short rwdsk_lba_ok
  3157 0000600B 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3158 0000600E 7408                <1>         je      short rwdsk_lba_fails
  3159 00006010 FE0D[DA700000]      <1> 	dec	byte [retry_count]
  3160 00006016 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3161                              <1> rwdsk_err2:	; 12/02/2022
  3162                              <1> rwdsk_lba_fails:
  3163 00006018 F9                  <1> 	stc
  3164                              <1> rwdsk_lba_ok:
  3165 00006019 5B                  <1> 	pop	ebx ; ***
  3166 0000601A 5E                  <1> 	pop	esi ; ****
  3167 0000601B C3                  <1> 	retn
  3168                              <1> rwdsk_lba_reset:
  3169 0000601C B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3170                              <1> 	;int	13h
  3171 0000601E E88EC5FFFF          <1>         call	int13h
  3172 00006023 73D7                <1> 	jnc     short rwdsk_lba_retry
  3173 00006025 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3174 00006027 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3175                              <1> 	;
  3176                              <1> 	; CHS read (convert LBA address to CHS values)	
  3177                              <1> rwdsk_chs:
  3178                              <1> 	; 10/07/2015
  3179 00006029 81EE[DA670000]      <1> 	sub	esi, drv.status
  3180 0000602F 89F1                <1> 	mov	ecx, esi
  3181 00006031 81C6[E1670000]      <1> 	add 	esi, drv.error
  3182                              <1> 	; 02/07/2015
  3183                              <1> 	; 16/06/2015
  3184                              <1>  	; 11/06/2015 
  3185 00006037 53                  <1> 	push	ebx ; ** ; buffer
  3186 00006038 D1E1                <1> 	shl	ecx, 1
  3187 0000603A 51                  <1> 	push	ecx ; * 
  3188                              <1> 	;
  3189 0000603B 89CB                <1> 	mov	ebx, ecx
  3190 0000603D 8835[D9700000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3191 00006043 31D2                <1> 	xor	edx, edx ; 0
  3192                              <1> 	; 04/02/2022
  3193                              <1> 	;sub	ecx, ecx 
  3194 00006045 81C3[B0670000]      <1>         add     ebx, drv.spt
  3195 0000604B 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3196                              <1> 		; EDX:EAX = LBA
  3197 0000604E F7F1                <1> 	div	ecx
  3198 00006050 88D1                <1> 	mov	cl, dl	; sector number - 1
  3199 00006052 FEC1                <1> 	inc	cl	; sector number (1 based)
  3200 00006054 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3201                              <1> 	;push	cx
  3202                              <1>         ; 04/02/2022
  3203 00006055 51                  <1> 	push	ecx
  3204 00006056 81C3[A2670000]      <1>         add     ebx, drv.heads
  3205 0000605C 668B0B              <1> 	mov	cx, [ebx] ; heads
  3206 0000605F 31D2                <1> 	xor	edx, edx
  3207                              <1> 		; EAX = cylinders * heads + head
  3208 00006061 F7F1                <1> 	div	ecx
  3209                              <1> 	;pop	cx     ; sector number
  3210                              <1> 	; 04/02/2022
  3211 00006063 59                  <1> 	pop	ecx
  3212 00006064 88D6                <1> 	mov	dh, dl ; head number
  3213 00006066 8A15[8B670000]      <1> 	mov	dl, [drv]
  3214 0000606C 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3215 0000606E C0E406              <1> 	shl	ah, 6
  3216 00006071 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3217                              <1> 		       ; sector (bits 0-7)
  3218 00006073 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3219                              <1> 		; CL = sector (bits 0-5)
  3220                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3221                              <1> 		; CH = cylinder (bits 0-7)
  3222                              <1> 		; DH = head
  3223                              <1> 		; DL = drive
  3224                              <1> 	;
  3225 00006074 C605[DA700000]04    <1> 	mov	byte [retry_count], 4
  3226                              <1> rwdsk_retry:	
  3227 0000607B 8A25[D9700000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3228 00006081 B001                <1> 	mov	al, 1 ; sector count	
  3229                              <1> 	;int	13h
  3230 00006083 E829C5FFFF          <1> 	call	int13h
  3231 00006088 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3232 0000608A 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3233 0000608C 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3234 0000608F 7408                <1> 	je	short rwdsk_fails
  3235 00006091 FE0D[DA700000]      <1> 	dec	byte [retry_count]
  3236 00006097 7504                <1> 	jnz	short rwdsk_reset
  3237                              <1> rwdsk_fails:
  3238 00006099 F9                  <1> 	stc
  3239                              <1> rwdsk_ok:
  3240 0000609A 5B                  <1> 	pop	ebx ; ***
  3241 0000609B 5E                  <1> 	pop	esi ; ****
  3242 0000609C C3                  <1> 	retn
  3243                              <1> rwdsk_reset:
  3244                              <1> 	; 02/02/2015
  3245 0000609D 28E4                <1> 	sub	ah, ah
  3246 0000609F 80FA80              <1> 	cmp	dl, 80h
  3247 000060A2 7202                <1> 	jb	short rwdsk_fd_reset
  3248 000060A4 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3249                              <1> rwdsk_fd_reset:
  3250                              <1> 	;int	13h
  3251 000060A6 E806C5FFFF          <1>         call	int13h
  3252 000060AB 73CE                <1> 	jnc	short rwdsk_retry
  3253 000060AD 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3254 000060AF EBE9                <1> 	jmp 	short rwdsk_ok
  3255                              <1> 
  3256                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3257                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3258                              <1> ;
  3259                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3260                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3261                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3262                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3263                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3264                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3265                              <1> ; as in original unix v1.
  3266                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3267                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3268                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3269                              <1> ;
  3270                              <1> ; Erdogan tan (10/07/2015) 
  3271                              <1> 
  3272                              <1> ;drum: / interrupt handler
  3273                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3274                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3275                              <1> ;                                      / error
  3276                              <1> ;               br 3f / no, error
  3277                              <1> ;       br      2f / error
  3278                              <1> ;
  3279                              <1> ;disk:
  3280                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3281                              <1> ;       jmp     *$0f
  3282                              <1> ;0:
  3283                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3284                              <1> ;      	        br 3f / no, errors
  3285                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3286                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3287                              <1> ;                        / to 1f
  3288                              <1> ;       br      4f
  3289                              <1> ;1:
  3290                              <1> ;       bit     $20000,rkcs
  3291                              <1> ;       beq     4f / wait for seek complete
  3292                              <1> ;       mov     $0b,0b-2
  3293                              <1> ;       mov     rkap,r1
  3294                              <1> ;2:
  3295                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3296                              <1> ;                          / the disk buffer
  3297                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3298                              <1> ;       inc     r1
  3299                              <1> ;       asr     (r1)
  3300                              <1> ;       asr     (r1)
  3301                              <1> ;       asr     (r1) / reissue request
  3302                              <1> ;       dec     r1
  3303                              <1> ;3:
  3304                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3305                              <1> ;       mov     ac,-(sp)
  3306                              <1> ;       mov     mq,-(sp) / put these on the stack
  3307                              <1> ;       mov     sc,-(sp)
  3308                              <1> ;       jsr     r0,poke
  3309                              <1> ;       mov     (sp)+,sc
  3310                              <1> ;       mov     (sp)+,mq / pop them off stack
  3311                              <1> ;       mov     (sp)+,ac
  3312                              <1> ;4:
  3313                              <1> ;       jmp     retisp / u4-3
  3314                              <1> ;
  3315                              <1> ;trapt:                  / r2 points to the
  3316                              <1> ;       mov     (r0)+,r2 / device control register
  3317                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3318                              <1> ;       tst     (sp)+
  3319                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3320                              <1> ;       bge     4b / device still active so branch
  3321                              <1> ;       bit     (r0),active / was device busy?
  3322                              <1> ;       beq     4b / no, stray interrupt
  3323                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3324                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3325                              <1> ;       bge     2f / if no error jump to 2f
  3326                              <1> ;       tst     (r0)+ / skip on error
  3327                              <1> ; 2:
  3328                              <1> ;       jmp     (r0)
  2056                                  %include 'u9.s'        ; 29/06/2015
  2057                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYS9.INC
  2058                              <1> ; Last Modification: 13/06/2022
  2059                              <1> ; ----------------------------------------------------------------------------
  2060                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2061                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2062                              <1> ;
  2063                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2064                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2065                              <1> ; <Bell Laboratories (17/3/1972)>
  2066                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2067                              <1> ;
  2068                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2069                              <1> ;
  2070                              <1> ; ****************************************************************************
  2071                              <1> ; 21/11/2015
  2072                              <1> 
  2073                              <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20) - Printer BIOS (Functions)
  2074                              <1> ; 04/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2075                              <1> ; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2076                              <1> 
  2077                              <1> getch:
  2078                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2079                              <1> 	; 30/06/2015
  2080                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2081 000060B1 28C0                <1> 	sub	al, al ; 0
  2082                              <1> getch_q: ; 06/08/2015
  2083 000060B3 8A25[C66C0000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2084 000060B9 EB06                <1>         jmp     short getc_n
  2085                              <1> 
  2086                              <1> getc: 
  2087                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2088                              <1> 	; 12/11/2015
  2089                              <1> 	; 15/09/2015
  2090                              <1> 	; 01/07/2015
  2091                              <1> 	; 30/06/2015
  2092                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2093                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2094                              <1> 	;
  2095                              <1> 	; Retro UNIX 8086 v1 modification !
  2096                              <1> 	; 
  2097                              <1> 	; 'getc' gets (next) character 
  2098                              <1> 	;	 from requested TTY (keyboard) buffer 
  2099                              <1> 	; INPUTS ->
  2100                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2101                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2102                              <1> 	;	(Keyboard buffer will point to 
  2103                              <1> 	;			next character at next call)
  2104                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2105                              <1> 	;	(Keyboard buffer will point to 
  2106                              <1> 	;			current character at next call)
  2107                              <1> 	; OUTPUTS ->
  2108                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2109                              <1> 	;     			 ZF=0 -> AX has (current) character
  2110                              <1> 	;      AL = ascii code
  2111                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2112                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2113                              <1> 	; Original UNIX V1 'getc': 
  2114                              <1> 	;		get a character off character list
  2115                              <1> 	;
  2116                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2117                              <1> 	;
  2118                              <1> 	; 30/06/2015 (32 bit modifications)
  2119                              <1> 	; 16/07/2013
  2120                              <1> 	; mov 	[getctty], ah
  2121                              <1> 	;
  2122                              <1> 
  2123 000060BB 8A25[AA700000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2124                              <1> getc_n:
  2125                              <1> 	; 30/06/2015
  2126 000060C1 08E4                <1> 	or	ah, ah
  2127 000060C3 740D                <1> 	jz	short getc0 
  2128 000060C5 D0E4                <1> 	shl	ah, 1
  2129 000060C7 0FB6DC              <1> 	movzx	ebx, ah
  2130 000060CA 81C3[C86C0000]      <1> 	add	ebx, ttychr
  2131 000060D0 EB05                <1> 	jmp	short getc1
  2132                              <1> getc0:
  2133 000060D2 BB[C86C0000]        <1> 	mov	ebx, ttychr
  2134                              <1> getc1:
  2135 000060D7 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2136                              <1> 				; (by kb_int)	
  2137 000060DA 6609C9              <1> 	or	cx, cx
  2138 000060DD 7507                <1> 	jnz	short getc2
  2139 000060DF 20C0                <1> 	and 	al, al
  2140 000060E1 7415                <1> 	jz	short getc_s
  2141                              <1> 	;xor	ax, ax
  2142                              <1> 	; 24/12/2021
  2143 000060E3 31C0                <1> 	xor	eax, eax
  2144 000060E5 C3                  <1> 	retn
  2145                              <1> getc2:	
  2146 000060E6 20C0                <1> 	and	al, al
  2147 000060E8 6689C8              <1> 	mov	ax, cx
  2148 000060EB 66B90000            <1> 	mov	cx, 0
  2149 000060EF 7506                <1> 	jnz	short getc3
  2150                              <1> getc_sn:
  2151 000060F1 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2152 000060F4 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2153                              <1> getc3:
  2154 000060F7 C3                  <1> 	retn
  2155                              <1> getc_s:
  2156                              <1> 	; 12/11/2015
  2157                              <1> 	; 15/09/2015
  2158                              <1> 	; 01/07/2015
  2159                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2160                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2161                              <1> 	;
  2162                              <1> 	; tty  of the current process is not 
  2163                              <1> 	; current tty (ptty); so, current process only 
  2164                              <1> 	; can use keyboard input when its tty becomes 
  2165                              <1> 	; current tty (ptty).
  2166                              <1> 	; 'sleep' is for preventing an endless lock
  2167                              <1> 	; during this tty input request.
  2168                              <1> 	; (Because, the user is not looking at the video page
  2169                              <1> 	; of the process to undersand there is a keyboard
  2170                              <1> 	; input request.)
  2171                              <1> 	;
  2172                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2173                              <1> 	;
  2174                              <1> 	; 05/10/2013
  2175                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2176                              <1> 	;
  2177                              <1> 	; 10/10/2013
  2178                              <1> gcw0:
  2179 000060F8 B10A                <1> 	mov	cl, 10 ; ch = 0
  2180                              <1> gcw1:	
  2181                              <1> 	; 12/11/2015
  2182 000060FA E8D8DAFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2183                              <1> 	; 10/10/2013
  2184 000060FF E877EEFFFF          <1> 	call	idle
  2185 00006104 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2186                              <1> 				; (by kb_int)
  2187 00006107 6609C0              <1> 	or	ax, ax
  2188                              <1> ;	jnz	short gcw3
  2189 0000610A 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2190                              <1> 	; 30/06/2015
  2191 0000610C FEC9                <1> 	dec	cl
  2192 0000610E 75EA                <1> 	jnz	short gcw1
  2193                              <1> 	;
  2194 00006110 8A25[AA700000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2195                              <1> ;	; 10/12/2013
  2196                              <1> ;	cmp 	ah, [ptty]
  2197                              <1> ;	jne	short gcw2
  2198                              <1> ;	; 14/02/2014
  2199                              <1> ;	cmp	byte [u.uno], 1
  2200                              <1> ;	jna	short gcw0		
  2201                              <1> ;gcw2:
  2202 00006116 E8EDEEFFFF          <1> 	call	sleep
  2203                              <1> 	;
  2204                              <1> 	; 20/09/2013
  2205 0000611B 8A25[AA700000]      <1> 	mov	ah, [u.ttyn]
  2206 00006121 30C0                <1> 	xor 	al, al
  2207 00006123 EB9C                <1> 	jmp	short getc_n
  2208                              <1> ;gcw3:
  2209                              <1> gcw2: 	; 15/09/2015
  2210                              <1> 	; 10/10/2013
  2211 00006125 30C9                <1> 	xor	cl, cl
  2212 00006127 EBC8                <1> 	jmp	short getc_sn
  2213                              <1> 
  2214                              <1> putc:	
  2215                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2216                              <1> 	; 13/08/2015
  2217                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2218                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2219                              <1> 	;
  2220                              <1> 	; Retro UNIX 8086 v1 modification !
  2221                              <1> 	; 
  2222                              <1> 	; 'putc' puts a character 
  2223                              <1> 	;	 onto requested (tty) video page or
  2224                              <1> 	;	 serial port
  2225                              <1> 	; INPUTS ->
  2226                              <1> 	;     AL = ascii code of the character
  2227                              <1> 	;     AH = video page (tty) number (0 to 7)
  2228                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2229                              <1> 	; OUTPUTS ->
  2230                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2231                              <1> 	;      			ZF=0 -> AX has (current) character
  2232                              <1> 	;     cf=0 and AH = 0 -> no error
  2233                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2234                              <1> 	; 
  2235                              <1> 	; Original UNIX V1 'putc': 
  2236                              <1> 	;     put a character at the end of character list
  2237                              <1> 	;
  2238                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2239                              <1> 	;
  2240 00006129 80FC07              <1> 	cmp	ah, 7
  2241                              <1>         ;ja	sndc
  2242 0000612C 770A                <1>         ja      short sndc ; 24/12/2024
  2243                              <1> 	; 30/06/2015
  2244 0000612E 0FB6DC              <1> 	movzx	ebx, ah
  2245                              <1> 	; 13/08/2015
  2246 00006131 B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2247 00006133 E9A2B2FFFF          <1> 	jmp	write_tty ; 'video.inc'
  2248                              <1> 
  2249                              <1> sndc:   ; <Send character>
  2250                              <1> 	;
  2251                              <1> 	; 12/01/2022
  2252                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2253                              <1> 	; 17/11/2015
  2254                              <1> 	; 16/11/2015
  2255                              <1> 	; 11/11/2015
  2256                              <1> 	; 10/11/2015
  2257                              <1> 	; 09/11/2015
  2258                              <1> 	; 08/11/2015
  2259                              <1> 	; 07/11/2015
  2260                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2261                              <1> 	; 29/10/2015
  2262                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2263                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2264                              <1> 	;
  2265                              <1> 	; Retro UNIX 8086 v1 feature only !
  2266                              <1> 	;
  2267                              <1> 	; ah = [u.ttyn]
  2268                              <1> 	;
  2269                              <1> 	; 30/06/2015
  2270 00006138 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2271                              <1> 	; 07/11/2015
  2272 0000613B 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2273                              <1> sndc0:
  2274                              <1> 	; 07/11/2015
  2275 0000613E E813EFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2276 00006143 7405                <1> 	jz	short sndc1
  2277 00006145 E88DDAFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2278                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2279                              <1> sndc1:
  2280                              <1> 	; 16/11/2015
  2281                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2282                              <1> 	; 24/12/2021
  2283 0000614A 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2284                              <1> sndcx:
  2285 0000614C 8A83[0A6D0000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2286 00006152 8AA3[086D0000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2287                              <1> 	;
  2288                              <1> 	; 17/11/2015
  2289                              <1> 	; check 'request for response' status
  2290 00006158 80BB[046D0000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2291 0000615F 740A                <1> 	jz	short query
  2292                              <1> response:
  2293 00006161 FE05[076D0000]      <1> 	inc 	byte [comqr] ; query or response status
  2294 00006167 B0FF                <1> 	mov	al, 0FFh	 
  2295 00006169 EB14                <1> 	jmp	short sndc3
  2296                              <1> query:
  2297 0000616B 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2298 0000616D 750E                <1> 	jnz 	short sndc2 ; normal character
  2299                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2300                              <1> 	;je	short sndc2  ; yes, already responded
  2301                              <1> 	; 16/11/2015
  2302                              <1> 	; query: request for response (again)
  2303 0000616F 8883[086D0000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2304 00006175 FE05[076D0000]      <1> 	inc 	byte [comqr] ; query or response status
  2305 0000617B EB02                <1> 	jmp	short sndc3
  2306                              <1> sndc2:
  2307 0000617D 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2308                              <1> sndc3:
  2309 0000617F 8883[0A6D0000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2310 00006185 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2311                              <1> 	; 30/06/2015
  2312 00006187 E8FAD3FFFF          <1> 	call	sp_status ; get serial port status
  2313                              <1> 	; AL = Line status, AH = Modem status
  2314                              <1> 	; 07/11/2015
  2315 0000618C A880                <1> 	test	al, 80h
  2316 0000618E 7504                <1> 	jnz	short sndc4
  2317 00006190 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2318 00006192 751A                <1> 	jnz	short sndc5
  2319                              <1> sndc4: 	; Check line status again
  2320                              <1> 	; 16/11/2015
  2321                              <1> 	;push	cx
  2322                              <1> 	; 24/12/2021
  2323 00006194 51                  <1> 	push	ecx
  2324                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2325                              <1> 	; 12/01/2022
  2326 00006195 31C9                <1> 	xor	ecx, ecx
  2327 00006197 B106                <1> 	mov	cl, 6
  2328 00006199 E833B3FFFF          <1> 	call	WAITF
  2329                              <1> 	;pop	cx
  2330                              <1> 	; 24/12/1021
  2331 0000619E 59                  <1> 	pop	ecx
  2332                              <1> 	;
  2333 0000619F 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2334 000061A1 E8E0D3FFFF          <1> 	call	sp_status ; get serial port status
  2335                              <1> 	; 16/11/2015
  2336                              <1> 	; 09/11/2015
  2337                              <1> 	; 08/11/2015
  2338 000061A6 A880                <1> 	test	al, 80h	; time out error
  2339 000061A8 7565                <1>         jnz     short sndc7
  2340 000061AA A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2341 000061AC 7461                <1>         jz	short sndc7
  2342                              <1> sndc5:  
  2343 000061AE 8A83[0A6D0000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2344 000061B4 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2345 000061B8 28DE                <1> 	sub	dh, bl
  2346 000061BA EE                  <1> 	out	dx, al	   ; send on serial port
  2347                              <1> 	; 10/11/2015
  2348                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2349                              <1> 	; (to improve text flow to the terminal)
  2350                              <1> 	; ('diskette.inc': 'WAITF')
  2351                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2352                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2353                              <1> 	;push	cx
  2354                              <1> 	; 24/12/2021
  2355 000061BB 51                  <1> 	push	ecx
  2356                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2357                              <1> 	; 12/01/2022
  2358 000061BC 29C9                <1> 	sub	ecx, ecx
  2359 000061BE B106                <1> 	mov	cl, 6
  2360 000061C0 E80CB3FFFF          <1> 	call	WAITF
  2361                              <1> 	;pop	cx
  2362                              <1> 	; 24/12/1021
  2363 000061C5 59                  <1> 	pop	ecx
  2364                              <1>     	;
  2365                              <1> 	; 07/11/2015
  2366 000061C6 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2367                              <1> 	;
  2368 000061C8 E8B9D3FFFF          <1> 	call	sp_status ; get serial port status
  2369                              <1> 	; AL = Line status, AH = Modem status
  2370                              <1> 	;
  2371 000061CD E884EEFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2372 000061D2 7405                <1> 	jz	short sndc6
  2373 000061D4 E8FED9FFFF          <1> 	call	intract ; quit (ctrl+break) check
  2374                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2375                              <1> sndc6:
  2376 000061D9 3C80                <1> 	cmp	al, 80h
  2377 000061DB 7332                <1> 	jnb	short sndc7		
  2378                              <1> 	;
  2379 000061DD 803D[076D0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2380 000061E4 7244                <1> 	jb	short sndc8 	; no, normal character
  2381 000061E6 883D[076D0000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2382                              <1> 	; 17/11/2015
  2383 000061EC E88AEDFFFF          <1> 	call	idle
  2384                              <1> 	;
  2385 000061F1 38BB[0A6D0000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2386                              <1>         ;ja	sndc2       ; response (will be followed by
  2387                              <1> 			    ; a normal character)
  2388                              <1> 	; 24/12/2021
  2389 000061F7 7602                <1> 	jna	short sndc_10
  2390 000061F9 EB82                <1> 	jmp	sndc2
  2391                              <1> sndc_10:
  2392                              <1> 	; Query request must be responded by the terminal
  2393                              <1> 	; before sending a normal character !
  2394 000061FB 53                  <1> 	push	ebx
  2395                              <1> 	;push	cx ; *** cl = character (to be sent)
  2396                              <1> 	; 24/12/2021
  2397 000061FC 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2398 000061FD 8A25[AA700000]      <1> 	mov	ah, [u.ttyn]
  2399 00006203 E800EEFFFF          <1> 	call	sleep ; this process will be awakened by
  2400                              <1> 		      ; received data available interrupt
  2401                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2402                              <1> 	; 24/12/2021
  2403 00006208 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2404 00006209 5B                  <1> 	pop	ebx
  2405 0000620A E93DFFFFFF          <1>         jmp	sndcx
  2406                              <1> sndc7:
  2407                              <1> 	 ; 16/11/2015
  2408 0000620F 803D[076D0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2409 00006216 7213                <1> 	jb	short sndc9 	; no
  2410                              <1> 	;
  2411 00006218 88BB[086D0000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2412 0000621E 88BB[0A6D0000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2413                              <1> 	;
  2414 00006224 883D[076D0000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2415                              <1> sndc8:
  2416 0000622A F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2417                              <1> sndc9:
  2418                              <1> 	; AL = Line status, AH = Modem status
  2419 0000622B C3                  <1> 	retn
  2420                              <1> 
  2421                              <1> get_cpos:
  2422                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2423                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2424                              <1> 	;
  2425                              <1> 	; INPUT -> bl = video page number
  2426                              <1> 	; RETURN -> dx = cursor position
  2427                              <1> 
  2428 0000622C 53                  <1> 	push	ebx
  2429 0000622D 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2430 00006230 D0E3                <1> 	shl	bl, 1
  2431 00006232 81C3[B66C0000]      <1> 	add	ebx, cursor_posn
  2432 00006238 668B13              <1> 	mov	dx, [ebx]
  2433 0000623B 5B                  <1> 	pop	ebx
  2434 0000623C C3                  <1> 	retn
  2435                              <1> 
  2436                              <1> read_ac_current:
  2437                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2438                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2439                              <1> 	;
  2440                              <1> 	; INPUT -> bl = video page number
  2441                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2442                              <1> 
  2443 0000623D E8FEB2FFFF          <1> 	call 	find_position ; 'video.inc'
  2444                              <1> 	; dx = status port
  2445                              <1> 	; esi = cursor location/address
  2446 00006242 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2447 00006248 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2448 0000624B C3                  <1> 	retn
  2449                              <1> 
  2450                              <1> syssleep:
  2451                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2452                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2453                              <1> 	;
  2454                              <1> 	; Retro UNIX 8086 v1 feature only
  2455                              <1> 	; (INPUT -> none)
  2456                              <1> 	;
  2457 0000624C 0FB61D[A5700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2458 00006253 8AA3[B76D0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2459 00006259 E8AAEDFFFF          <1> 	call	sleep
  2460 0000625E E990D8FFFF          <1> 	jmp	sysret
  2461                              <1> 
  2462                              <1> 	; 27/02/2022
  2463                              <1> 	; (u1.s, 'wttyc' & 'wpc_clr')
  2464                              <1> %if 0
  2465                              <1> 
  2466                              <1> vp_clr:
  2467                              <1> 	; Reset/Clear Video Page
  2468                              <1> 	;
  2469                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2470                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2471                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2472                              <1> 	;
  2473                              <1> 	; Retro UNIX 8086 v1 feature only !
  2474                              <1> 	;
  2475                              <1> 	; INPUTS -> 
  2476                              <1> 	;   BL = video page number	 
  2477                              <1> 	;
  2478                              <1> 	; OUTPUT ->
  2479                              <1> 	;   none
  2480                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2481                              <1> 	;
  2482                              <1> 	; 04/12/2013
  2483                              <1> 	sub	al, al
  2484                              <1> 	; al = 0 (clear video page)
  2485                              <1> 	; bl = video page
  2486                              <1> 	mov	ah, 07h
  2487                              <1> 	; ah = 7 (attribute/color)
  2488                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2489                              <1> 	; 24/12/2021
  2490                              <1> 	xor	ecx, ecx
  2491                              <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2492                              <1> 	call	scroll_up
  2493                              <1> 	; bl = video page
  2494                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2495                              <1> 	; 24/12/2021
  2496                              <1> 	xor	edx, edx 
  2497                              <1> 	jmp 	set_cpos
  2498                              <1> 
  2499                              <1> %endif
  2500                              <1> 
  2501                              <1> sysmsg:
  2502                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2503                              <1> 	; 11/11/2015
  2504                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2505                              <1> 	; Print user-application message on user's console tty
  2506                              <1> 	;
  2507                              <1> 	; Input -> EBX = Message address
  2508                              <1> 	;	   ECX = Message length (max. 255)
  2509                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2510                              <1> 	;
  2511 00006263 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2512                              <1> 	;ja	sysret ; nothing to do with big message size
  2513 00006269 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2514 0000626B 08C9                <1> 	or	cl, cl
  2515                              <1> 	;jz	sysret
  2516 0000626D 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2517 0000626F 20D2                <1> 	and	dl, dl
  2518 00006271 7502                <1> 	jnz	short sysmsg0
  2519 00006273 B207                <1> 	mov	dl, 07h ; default color
  2520                              <1> 		; (black background, light gray character)
  2521                              <1> sysmsg0:
  2522 00006275 891D[7C700000]      <1> 	mov	[u.base], ebx
  2523 0000627B 8815[C76C0000]      <1> 	mov	[ccolor], dl ; color attributes
  2524 00006281 89E5                <1> 	mov	ebp, esp
  2525 00006283 31DB                <1> 	xor	ebx, ebx ; 0
  2526 00006285 891D[84700000]      <1> 	mov	[u.nread], ebx ; 0
  2527                              <1> 	;
  2528 0000628B 381D[BD700000]      <1> 	cmp	[u.kcall], bl ; 0
  2529 00006291 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2530                              <1> 	;
  2531 00006293 890D[80700000]      <1> 	mov	[u.count], ecx
  2532 00006299 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2533                              <1> 	; 24/12/2021
  2534                              <1> 	; (dword alignment for esp)
  2535 0000629A F6C103              <1> 	test	cl, 3
  2536 0000629D 7404                <1> 	jz	short sysmsg_7
  2537 0000629F 80C903              <1> 	or	cl, 3
  2538 000062A2 41                  <1> 	inc	ecx
  2539                              <1> sysmsg_7:
  2540 000062A3 29CC                <1> 	sub	esp, ecx
  2541 000062A5 89E7                <1> 	mov	edi, esp
  2542 000062A7 89E6                <1> 	mov	esi, esp
  2543 000062A9 66891D[BB700000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2544                              <1> 	; 11/11/2015
  2545 000062B0 8A25[8C700000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2546                              <1> 	; 0 = none
  2547 000062B6 FECC                <1> 	dec	ah
  2548 000062B8 790C                <1> 	jns	short sysmsg1 
  2549 000062BA 8A1D[A5700000]      <1> 	mov	bl, [u.uno] ; process number	
  2550 000062C0 8AA3[B76D0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2551                              <1> sysmsg1:
  2552 000062C6 8825[AA700000]      <1> 	mov	[u.ttyn], ah
  2553                              <1> sysmsg2:
  2554 000062CC E804F5FFFF          <1> 	call	cpass
  2555 000062D1 7416                <1> 	jz	short sysmsg5
  2556 000062D3 AA                  <1> 	stosb
  2557 000062D4 20C0                <1> 	and	al, al
  2558 000062D6 75F4                <1> 	jnz	short sysmsg2
  2559                              <1> sysmsg3:
  2560 000062D8 80FC07              <1> 	cmp	ah, 7 ; tty number
  2561 000062DB 7711                <1> 	ja	short sysmsg6 ; serial port
  2562 000062DD E83E000000          <1> 	call	print_cmsg
  2563                              <1> sysmsg4:
  2564 000062E2 89EC                <1> 	mov	esp, ebp	
  2565                              <1> sysmsg8: ; 24/12/2021	
  2566 000062E4 E90AD8FFFF          <1> 	jmp	sysret
  2567                              <1> sysmsg5:
  2568 000062E9 C60700              <1> 	mov	byte [edi], 0
  2569 000062EC EBEA                <1> 	jmp	short sysmsg3
  2570                              <1> sysmsg6:
  2571 000062EE 8A06                <1> 	mov	al, [esi]
  2572 000062F0 E843FEFFFF          <1> 	call	sndc
  2573 000062F5 72EB                <1> 	jc	short sysmsg4
  2574 000062F7 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2575 000062FA 76E6                <1> 	jna	short sysmsg4
  2576 000062FC 46                  <1> 	inc 	esi
  2577 000062FD 8A25[AA700000]      <1> 	mov	ah, [u.ttyn]
  2578 00006303 EBE9                <1> 	jmp	short sysmsg6
  2579                              <1> 
  2580                              <1> sysmsgk: ; Temporary (01/07/2015)
  2581                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2582                              <1> 	; (ECX -character count- will not be considered)
  2583 00006305 8B35[7C700000]      <1> 	mov	esi, [u.base]
  2584 0000630B 8A25[C66C0000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2585 00006311 8825[AA700000]      <1> 	mov	[u.ttyn], ah
  2586 00006317 C605[BD700000]00    <1> 	mov	byte [u.kcall], 0
  2587 0000631E EBB8                <1> 	jmp	short sysmsg3
  2588                              <1> 	
  2589                              <1> print_cmsg: 
  2590                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2591                              <1> 	;
  2592                              <1> 	; print message (on user's console tty) 
  2593                              <1> 	;	with requested color
  2594                              <1> 	;
  2595                              <1> 	; INPUTS:
  2596                              <1> 	;	esi = message address
  2597                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2598                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2599                              <1> 	;
  2600 00006320 AC                  <1> 	lodsb
  2601                              <1> pcmsg1:
  2602 00006321 56                  <1> 	push 	esi
  2603 00006322 0FB61D[AA700000]    <1>         movzx   ebx, byte [u.ttyn]
  2604 00006329 8A25[C76C0000]      <1> 	mov	ah, [ccolor]
  2605 0000632F E8A6B0FFFF          <1> 	call 	write_tty
  2606 00006334 5E                  <1> 	pop	esi
  2607 00006335 AC                  <1> 	lodsb
  2608 00006336 20C0                <1> 	and 	al, al  ; 0
  2609 00006338 75E7                <1> 	jnz 	short pcmsg1
  2610 0000633A C3                  <1> 	retn
  2611                              <1> 
  2612                              <1> sysgeterr:
  2613                              <1> 	; 16/02/2022
  2614                              <1> 	; 09/12/2015
  2615                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2616                              <1> 	; Get last error number or page fault count
  2617                              <1> 	; (for debugging)
  2618                              <1> 	;
  2619                              <1> 	; Input -> EBX = return type
  2620                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2621                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2622                              <1> 	;	   FFFFFFFEh = total page fault count
  2623                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2624                              <1> 	;
  2625                              <1> 	; Output -> EAX = last error number or page fault count
  2626                              <1> 	;	   (depending on EBX input)
  2627                              <1> 	; 	
  2628 0000633B 21DB                <1> 	and 	ebx, ebx
  2629 0000633D 750F                <1> 	jnz	short glerr_2
  2630                              <1> glerr_0:
  2631 0000633F A1[AB700000]        <1> 	mov	eax, [u.error]
  2632                              <1> glerr_1:
  2633 00006344 A3[5C700000]        <1> 	mov	[u.r0], eax
  2634                              <1>  	;retn
  2635                              <1> 	; 16/02/2022 (BugFix)
  2636 00006349 E9A5D7FFFF          <1> 	jmp	sysret
  2637                              <1> glerr_2:
  2638 0000634E 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2639 0000634F 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2640 00006351 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2641 00006352 75EB                <1> 	jnz	short glerr_0
  2642 00006354 A1[506D0000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2643 00006359 EBE9                <1>         jmp     short glerr_1
  2644                              <1> glerr_3:
  2645 0000635B A1[BF700000]        <1> 	mov 	eax, [u.pfcount]
  2646 00006360 EBE2                <1> 	jmp	short glerr_1
  2647                              <1> 
  2648                              <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2649                              <1> ;	     - PRINTER BIOS (Functions)		
  2650                              <1> 
  2651                              <1> ;;; IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 ;;; 
  2652                              <1> ;
  2653                              <1> ;--- INT 17 H ------------------------------------------------------------------
  2654                              <1> ; PRINTER_IO								       :
  2655                              <1> ;	THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER		       :
  2656                              <1> ; INPUT 								       :
  2657                              <1> ;	(AH)= 00H  PRINT THE CHARACTER IN (AL)				       :
  2658                              <1> ;		    ON RETURN, (AH)= 1 IF CHARACTER NOT BE PRINTED (TIME OUT)  :
  2659                              <1> ;		    OTHER BITS SET AS ON NORMAL STATUS CALL		       :
  2660                              <1> ;	(AH)= 01H  INITIALIZE THE PRINTER PORT				       :
  2661                              <1> ;		    RETURNS WITH (AH) SET WITH PRINTER STATUS		       :
  2662                              <1> ;	(AH)= 02H  READ THE PRINTER STATUS INTO (AH)			       :
  2663                              <1> ;		   7	   6	   5	   4	   3	   2-1	   0	       :
  2664                              <1> ;		   |	   |	   |	   |	   |	   |	   |_TIME OUT  :
  2665                              <1> ;		   |	   |	   |	   |	   |	   |		       :
  2666                              <1> ;		   |	   |	   |	   |	   |	   |_ UNUSED	       :
  2667                              <1> ;		   |	   |	   |	   |	   |			       :
  2668                              <1> ;		   |	   |	   |	   |	   |_ 1 = I/O ERROR	       :
  2669                              <1> ;		   |	   |	   |	   |				       :
  2670                              <1> ;		   |	   |	   |	   |_ 1 = SELECTED		       :
  2671                              <1> ;		   |	   |	   |					       :
  2672                              <1> ;		   |	   |	   |_ 1 = OUT OF PAPER			       :
  2673                              <1> ;		   |	   |						       :
  2674                              <1> ;		   |	   |_ 1 = ACKNOWLEDGE				       :
  2675                              <1> ;		   |							       :
  2676                              <1> ;		   |_ 1 = NOT BUSY					       :
  2677                              <1> ;									       :
  2678                              <1> ;	(DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES       :
  2679                              <1> ;		IN @PRINTER_BASE AREA					       :
  2680                              <1> ; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S)     :
  2681                              <1> ; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS)     :
  2682                              <1> ;									       :
  2683                              <1> ; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGED TO CAUSE DIFFERENT	       :
  2684                              <1> ; TIME OUT WAITS. DEFAULT=20 * 4					       :
  2685                              <1> ;									       :
  2686                              <1> ; REGISTERS	(AH) IS MODIFIED WITH STATUS INFORMATION		       :
  2687                              <1> ;		ALL OTHERS UNCHANGED					       :
  2688                              <1> ;-------------------------------------------------------------------------------
  2689                              <1> 
  2690                              <1> int17h:
  2691                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2692                              <1> 	; (Derived from: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985)
  2693                              <1> 	;
  2694                              <1> 	; (Default printer port: 378h) ; LPT1
  2695                              <1> 	; (Number of printers = 1)
  2696                              <1> 	
  2697                              <1> 	PRINTER_BASE equ 378h ; LPT1
  2698                              <1> 	;PRINT_TIM_OUT equ 4*80*65536 
  2699                              <1> 			; (Ref: IBM PC-AT BIOS v2 PRT.ASM)	 
  2700                              <1> 
  2701                              <1> 	PRINT_TIM_OUT equ 36000 ; WAIT_PRN_NBUSY
  2702                              <1> 			; (Ref: AWARD BIOS 1999 ATORGS.ASM)		
  2703                              <1> 
  2704                              <1> 	; INPUT:
  2705                              <1> 	;	ah = 0 -> print the character in AL 
  2706                              <1> 	;		 (sys write with write count >0)
  2707                              <1> 	;	ah = 1 -> initialize printer port
  2708                              <1> 	;		 (sys open)	
  2709                              <1> 	;	ah = 2 -> read the printer status 
  2710                              <1> 	;		 (sys write with write count = 0)
  2711                              <1> 	; OUTPUT:
  2712                              <1> 	;	ah = printer status
  2713                              <1> 
  2714                              <1> 	; Modified registers: eax, ecx, edx
  2715                              <1> 
  2716                              <1> PRINTER_IO_1:
  2717 00006362 08E4                <1> 	or	ah, ah
  2718 00006364 7417                <1> 	jz	short _b20
  2719 00006366 FECC                <1> 	dec	ah
  2720 00006368 7444                <1> 	jz	short _b80
  2721                              <1> 	;dec 	ah
  2722                              <1> 	;jz	short _b50
  2723                              <1> _b50:
  2724                              <1> 	;-----	PRINTER STATUS
  2725                              <1> B50:
  2726 0000636A 50                  <1> 	push	eax		; SAVE (AL) REGISTER
  2727                              <1> B60:
  2728 0000636B 66BA7903            <1> 	mov	dx, PRINTER_BASE+1
  2729                              <1> 				; GET PRINTER ATTACHMENT BASE ADDRESS
  2730                              <1> 				; POINT TO CONTROL PORT
  2731 0000636F EC                  <1> 	in	al, dx		; PRE-CHARGE +BUSY LINE IF FLOATING
  2732 00006370 EC                  <1> 	in	al, dx		; GET PRINTER STATUS HARDWARE BITS
  2733 00006371 88C4                <1> 	mov	ah, al		; SAVE
  2734 00006373 80E4F8              <1> 	and	ah, 0F8h	; TURN OFF UNUSED BITS
  2735                              <1> B70:
  2736 00006376 5A                  <1> 	pop	edx		; RECOVER (AL) REGISTER
  2737 00006377 88D0                <1> 	mov	al, dl		; MOVE CHARACTER INTO (AL)
  2738 00006379 80F448              <1> 	xor	ah, 48h		; FLIP A COUPLE OF BITS
  2739                              <1> B10:
  2740 0000637C C3                  <1> 	retn			; RETURN FROM ROUTINE WITH STATUS IN AH
  2741                              <1> _b20:
  2742                              <1> 	;-----	PRINT THE CHARACTER IN (AL)
  2743 0000637D B9A08C0000          <1> 	mov	ecx, PRINT_TIM_OUT ; (1 second)
  2744                              <1> B20:
  2745 00006382 50                  <1> 	push	eax		; SAVE VALUE TO PRINT
  2746 00006383 66BA7803            <1> 	mov	dx, PRINTER_BASE
  2747 00006387 EE                  <1> 	out	dx, al		; OUTPUT CHARACTER TO DATA PORT
  2748 00006388 FEC2                <1> 	inc	dl		; POINT TO STATUS PORT
  2749                              <1> 
  2750                              <1> 	;-----	CHECK FOR PRINTER BUSY
  2751                              <1> B25:
  2752                              <1> 	;-----	WAIT BUSY
  2753                              <1> B35:
  2754 0000638A EC                  <1> 	in	al, dx		; GET STATUS
  2755 0000638B 88C4                <1> 	mov	ah, al		; STATUS TO (AH) ALSO
  2756 0000638D A880                <1> 	test	al, 80h		; IS THE PRINTER CURRENTLY BUSY? (*)
  2757 0000638F 750F                <1> 	jnz	short B40	; GO TO OUTPUT STROBE
  2758 00006391 E831000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2759 00006396 E2F2                <1> 	loop	B35		; LOOP IF YES (*)
  2760                              <1> 
  2761 00006398 80CC01              <1> 	or	ah, 1		; SET ERROR FLAG
  2762 0000639B 80E4F9              <1> 	and	ah, 0F9h	; TURN OFF THE UNUSED BITS
  2763 0000639E EBD6                <1> 	jmp	short B70	; RETURN WITH ERROR FLAG SET
  2764                              <1> 
  2765                              <1> B40:				; SEND STROBE PULSE
  2766 000063A0 B00D                <1> 	mov	al, 0Dh		; SET THE STROBE LOW (BIT ON)
  2767 000063A2 6642                <1> 	inc	dx		; OUTPUT STROBE TO CONTROL PORT
  2768 000063A4 FA                  <1> 	cli			; PREVENT INTERRUPT PULSE STRETCHING
  2769 000063A5 EE                  <1> 	out	dx, al		; OUTPUT STROBE BIT > 1us < 5us
  2770                              <1> 	; IODELAY
  2771                              <1> 	;jmp	short $+2	; I/O DELAY TO ALLOW FOR LINE LOADING
  2772                              <1> 	;jmp	short $+2	; AND FOR CORRECT PULSE WIDTH
  2773                              <1> 	; NEWIODELAY
  2774 000063A6 E6EB                <1> 	out	0EBh, al
  2775                              <1> 
  2776 000063A8 B00C                <1> 	mov	al, 0Ch		; SET THE -STROBE HIGH
  2777 000063AA EE                  <1> 	out	dx, al
  2778 000063AB FB                  <1> 	sti			; INTERRUPTS BACK ON
  2779                              <1> 	;pop	eax		; RECOVER THE OUTPUT CHAR
  2780                              <1> 	;jmp	short B50
  2781 000063AC EBBD                <1> 	jmp	short B60
  2782                              <1> 
  2783                              <1> _b80:
  2784                              <1> 	;-----	INITIALIZE THE PRINTER PORT
  2785                              <1> B80:
  2786 000063AE 50                  <1> 	push	eax		; SAVE (AL)
  2787 000063AF 66BA7A03            <1> 	mov	dx, PRINTER_BASE+2 ; POINT TO OUTPUT PORT
  2788 000063B3 B008                <1> 	mov	al, 8		; SET INIT LINE LOW
  2789 000063B5 EE                  <1> 	out	dx, al
  2790                              <1> 	;mov	eax, 1000*4	; ADJUST FOR INITIALIZATION DELAY LOOP
  2791 000063B6 B989080000          <1> 	mov	ecx, WAIT_PRN_INIT ; (65536 micro seconds)
  2792                              <1> B90:				; INIT_LOOP
  2793                              <1> 	;dec	eax		; LOOP FOR RESET TO TAKE
  2794                              <1> 	;jnz	short B90	; INIT_LOOP
  2795 000063BB E807000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2796 000063C0 E2F9                <1> 	loop	B90	
  2797 000063C2 B00C                <1> 	mov	al, 0Ch		; NO INTERRUPTS, NON AUTO LF, INIT HIGH
  2798 000063C4 EE                  <1> 	out	dx, al
  2799 000063C5 EBA4                <1> 	jmp	short B60	; EXIT THROUGH STATUS ROUTINE
  2800                              <1> 
  2801                              <1> 
  2802                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2803                              <1> ; -------------------------------------------------------------------
  2804                              <1> ;
  2805                              <1> ;;Wait while printer initializes should be 65,536 microseconds.
  2806                              <1> ;;65536/30 = 2185
  2807                              <1> ;			PUBLIC	WAIT_PRN_INIT_LO
  2808                              <1> ;WAIT_PRN_INIT_LO	DW	2185
  2809                              <1> ;			PUBLIC	WAIT_PRN_INIT_HI
  2810                              <1> ;WAIT_PRN_INIT_HI	DW	0
  2811                              <1> ;
  2812                              <1> WAIT_PRN_INIT equ 2185 ; 12/06/2022
  2813                              <1> ;
  2814                              <1> ;;Wait for printer not busy should be 1,080,000 microseconds.
  2815                              <1> ;;Memory refresh =15 us, therefore memory refresh period = 30 Us.
  2816                              <1> ;;1,080,000 / 30 = 36,000
  2817                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_LO
  2818                              <1> ;WAIT_PRN_NBUSY_LO	DW	36000
  2819                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_HI
  2820                              <1> ;WAIT_PRN_NBUSY_HI	DB	0
  2821                              <1> ;
  2822                              <1> ;WAIT_PRN_NBUSY	equ 36000 ; 12/06/2022
  2823                              <1> 
  2824                              <1> ; AWARD BIOS - 1999 - ATORGS.ASM (27/5/1999)
  2825                              <1> ; ------------------------------------------
  2826                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2827                              <1> ;   	INPUT: BX:CX = number of refresh periods to wait
  2828                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2829                              <1> ;	OUTPUT: BX:CX destroyed.
  2830                              <1> ;
  2831                              <1> ;	SAVES:	AX (except when NO STACK)
  2832                              <1> ;
  2833                              <1> ;	NOTES:	This routine can be (and is) used with no stack. When
  2834                              <1> ;		used this way, AX is assumed to be destroyed.
  2835                              <1> 
  2836                              <1> WAIT_REFRESH:
  2837                              <1> 	; 13/06/2022
  2838                              <1> 	; Modified for Retro UNIX 386 v1
  2839                              <1> 	
  2840                              <1> 	; (wait for 30 micro seconds)
  2841                              <1> 
  2842                              <1> 	SYS1	equ 61h ; PORT_B
  2843                              <1> 
  2844                              <1> WR_SHORT:
  2845 000063C7 50                  <1> 	push	eax
  2846                              <1> WR_STAT_0:
  2847 000063C8 E461                <1> 	in	al, SYS1	; wait for high to low
  2848 000063CA A810                <1> 	test	al, 10h		; transition on memory
  2849 000063CC 75FA                <1> 	jnz	short WR_STAT_0 
  2850                              <1> WR_STAT_1:
  2851 000063CE E461                <1> 	in	al, SYS1
  2852 000063D0 A810                <1> 	test	al, 10h
  2853 000063D2 74FA                <1> 	jz	short WR_STAT_1
  2854 000063D4 58                  <1> 	pop	eax
  2855 000063D5 C3                  <1> 	retn
  2057                                  
  2058                                  ; 07/03/2015
  2059                                  ; Temporary Code
  2060                                  display_disks:
  2061 000063D6 803D[8E670000]00        	cmp 	byte [fd0_type], 0
  2062 000063DD 7605                    	jna 	short ddsks1
  2063 000063DF E87D000000              	call	pdskm
  2064                                  ddsks1:
  2065 000063E4 803D[8F670000]00        	cmp	byte [fd1_type], 0
  2066 000063EB 760C                    	jna	short ddsks2
  2067 000063ED C605[7D690000]31        	mov	byte [dskx], '1'
  2068 000063F4 E868000000              	call	pdskm
  2069                                  ddsks2:
  2070 000063F9 803D[90670000]00        	cmp	byte [hd0_type], 0
  2071 00006400 7654                    	jna	short ddsk6
  2072 00006402 66C705[7B690000]68-     	mov	word [dsktype], 'hd'
  2072 0000640A 64                 
  2073 0000640B C605[7D690000]30        	mov	byte [dskx], '0'
  2074 00006412 E84A000000              	call	pdskm
  2075                                  ddsks3:
  2076 00006417 803D[91670000]00        	cmp	byte [hd1_type], 0
  2077 0000641E 7636                    	jna	short ddsk6
  2078 00006420 C605[7D690000]31        	mov	byte [dskx], '1'
  2079 00006427 E835000000              	call	pdskm
  2080                                  ddsks4:
  2081 0000642C 803D[92670000]00        	cmp	byte [hd2_type], 0
  2082 00006433 7621                    	jna	short ddsk6
  2083 00006435 C605[7D690000]32        	mov	byte [dskx], '2'
  2084 0000643C E820000000              	call	pdskm
  2085                                  ddsks5:
  2086 00006441 803D[93670000]00        	cmp	byte [hd3_type], 0
  2087 00006448 760C                    	jna	short ddsk6
  2088 0000644A C605[7D690000]33        	mov	byte [dskx], '3'
  2089 00006451 E80B000000              	call	pdskm
  2090                                  ddsk6:
  2091 00006456 BE[8C690000]            	mov	esi, nextline
  2092 0000645B E806000000              	call	pdskml
  2093                                  pdskm_ok:
  2094 00006460 C3                      	retn
  2095                                  pdskm:
  2096 00006461 BE[79690000]            	mov	esi, dsk_ready_msg
  2097                                  pdskml:	
  2098 00006466 AC                      	lodsb
  2099 00006467 08C0                    	or	al, al
  2100 00006469 74F5                    	jz	short pdskm_ok
  2101 0000646B 56                      	push	esi
  2102 0000646C 31DB                    	xor	ebx, ebx ; 0
  2103                                  			; Video page 0 (bl=0)
  2104 0000646E B407                    	mov	ah, 07h ; Black background, 
  2105                                  			; light gray forecolor
  2106 00006470 E865AFFFFF              	call	write_tty
  2107 00006475 5E                      	pop	esi
  2108 00006476 EBEE                    	jmp	short pdskml
  2109                                  
  2110 00006478 90<rep 8h>              align 16
  2111                                  
  2112                                  gdt:	; Global Descriptor Table
  2113                                  	; (30/07/2015, conforming cs)
  2114                                  	; (26/03/2015)
  2115                                  	; (24/03/2015, tss)
  2116                                  	; (19/03/2015)
  2117                                  	; (29/12/2013)
  2118                                  	;
  2119 00006480 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2120                                  	; 18/08/2014
  2121                                  			; 8h kernel code segment, base = 00000000h		
  2122 00006488 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2123                                  			; 10h kernel data segment, base = 00000000h	
  2124 00006490 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2125                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2126 00006498 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2127                                  			; 23h user data segment, base address = 400000h ; CORE
  2128 000064A0 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2129                                  			; Task State Segment
  2130 000064A8 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2131                                  			       ;  no IO permission in ring 3)
  2132                                  gdt_tss0:
  2133 000064AA 0000                    	dw 0  ; TSS base address, bits 0-15 
  2134                                  gdt_tss1:
  2135 000064AC 00                      	db 0  ; TSS base address, bits 16-23 
  2136                                  	      		; 49h	
  2137 000064AD E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2138 000064AE 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2139                                  gdt_tss2:
  2140 000064AF 00                      	db 0  ; TSS base address, bits 24-31 
  2141                                  
  2142                                  gdt_end:
  2143                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2144                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2145                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2146                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2147                                  
  2148                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2149                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2150                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2151                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2152                                  		; W= Writeable, A= Accessed
  2153                                  	
  2154                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2155                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2156                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2157                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2158                                  
  2159                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2160                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2161                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2162                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2163                                  	
  2164                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2165                                  
  2166                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2167                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2168                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2169                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2170                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2171                                  		; AVL= Available to programmers	
  2172                                  
  2173                                  gdtd:
  2174 000064B0 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2175 000064B2 [80640000]                      dd gdt			; Address of the GDT
  2176                                  
  2177                                  	; 20/08/2014
  2178                                  idtd:
  2179 000064B6 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2180 000064B8 [306A0000]                      dd idt			; Address of the IDT
  2181                                  
  2182                                  Align 4
  2183                                  
  2184                                  	; 21/08/2014
  2185                                  ilist:
  2186                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2187                                  	;
  2188                                  	; Exception list
  2189                                  	; 25/08/2014	
  2190 000064BC [3B080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2191 000064C0 [42080000]              	dd	exc1	
  2192 000064C4 [49080000]              	dd 	exc2	
  2193 000064C8 [50080000]              	dd	exc3	
  2194 000064CC [54080000]              	dd	exc4	
  2195 000064D0 [58080000]              	dd	exc5	
  2196 000064D4 [5C080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2197 000064D8 [60080000]              	dd	exc7	
  2198 000064DC [64080000]              	dd	exc8	
  2199 000064E0 [68080000]              	dd	exc9	
  2200 000064E4 [6C080000]              	dd 	exc10	
  2201 000064E8 [70080000]              	dd	exc11
  2202 000064EC [74080000]              	dd	exc12
  2203 000064F0 [78080000]              	dd	exc13	; 0Dh, General Protection Fault
  2204 000064F4 [7C080000]              	dd 	exc14	; 0Eh, Page Fault
  2205 000064F8 [80080000]              	dd	exc15
  2206 000064FC [84080000]              	dd	exc16
  2207 00006500 [88080000]              	dd	exc17
  2208 00006504 [8C080000]              	dd 	exc18
  2209 00006508 [90080000]              	dd	exc19
  2210 0000650C [94080000]              	dd 	exc20
  2211 00006510 [98080000]              	dd	exc21
  2212 00006514 [9C080000]              	dd	exc22
  2213 00006518 [A0080000]              	dd	exc23
  2214 0000651C [A4080000]              	dd 	exc24
  2215 00006520 [A8080000]              	dd	exc25
  2216 00006524 [AC080000]              	dd	exc26
  2217 00006528 [B0080000]              	dd	exc27
  2218 0000652C [B4080000]              	dd 	exc28
  2219 00006530 [B8080000]              	dd	exc29
  2220 00006534 [BC080000]              	dd 	exc30
  2221 00006538 [C0080000]              	dd	exc31
  2222                                  	; Interrupt list
  2223 0000653C [77060000]              	dd	timer_int	; INT 20h
  2224                                  		;dd	irq0	
  2225 00006540 [7C0B0000]              	dd	keyb_int	; 27/08/2014
  2226                                  		;dd	irq1
  2227 00006544 [95070000]              	dd	irq2
  2228                                  		; COM2 int
  2229 00006548 [99070000]              	dd	irq3
  2230                                  		; COM1 int
  2231 0000654C [A4070000]              	dd	irq4
  2232 00006550 [AF070000]              	dd	irq5
  2233                                  ;DISKETTE_INT: ;06/02/2015
  2234 00006554 [5E250000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2235                                  		;dd	irq6
  2236                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2237                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2238 00006558 [2B0B0000]              	dd	default_irq7	; 25/02/2015
  2239                                  		;dd	irq7
  2240                                  ; Real Time Clock Interrupt
  2241 0000655C [C9090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2242                                  		;dd	irq8	; INT 28h
  2243 00006560 [BF070000]              	dd	irq9
  2244 00006564 [C3070000]              	dd	irq10
  2245 00006568 [C7070000]              	dd	irq11
  2246 0000656C [CB070000]              	dd	irq12
  2247 00006570 [CF070000]              	dd	irq13
  2248                                  ;HDISK_INT1:  ;06/02/2015 	
  2249 00006574 [852D0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2250                                  		;dd	irq14
  2251                                  ;HDISK_INT2:  ;06/02/2015
  2252 00006578 [A82D0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2253                                  		;dd	irq15	; INT 2Fh
  2254                                  		; 14/08/2015
  2255 0000657C [DB390000]              	dd	sysent		; INT 30h (system calls)
  2256                                  	
  2257                                  	;dd	ignore_int
  2258 00006580 00000000                	dd	0
  2259                                  
  2260                                  ;;;
  2261                                  ;;; 11/03/2015
  2262                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2263                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - KYBDATA.INC
  2264                              <1> ; Last Modification: 13/06/2022
  2265                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2266                              <1> ;
  2267                              <1> ; ///////// KEYBOARD DATA ///////////////
  2268                              <1> 
  2269                              <1> ; 11/03/2015
  2270                              <1> ; 05/12/2014
  2271                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2272                              <1> ; 03/06/86  KEYBOARD BIOS
  2273                              <1> 
  2274                              <1> ;---------------------------------------------------------------------------------
  2275                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2276                              <1> ;---------------------------------------------------------------------------------
  2277                              <1> 
  2278                              <1> ;-----	TABLES FOR ALT CASE ------------
  2279                              <1> ;-----	ALT-INPUT-TABLE 
  2280 00006584 524F50514B          <1> K30:	db	82,79,80,81,75
  2281 00006589 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2282                              <1> ;-----	SUPER-SHIFT-TABLE 
  2283 0000658E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2284 00006594 161718191E1F        <1> 	db	22,23,24,25,30,31
  2285 0000659A 202122232425        <1> 	db	32,33,34,35,36,37
  2286 000065A0 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2287 000065A6 3132                <1> 	db	49,50
  2288                              <1> 
  2289                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2290                              <1> ;-----	KEY_TABLE 
  2291 000065A8 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2292 000065A9 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2293 000065AE 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2294                              <1> _K6L    equ     $-_K6
  2295                              <1> 
  2296                              <1> ;-----	MASK_TABLE
  2297 000065B0 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2298 000065B1 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2299 000065B6 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2300                              <1> 
  2301                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2302 000065B8 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2303 000065BE 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2304                              <1> 	;db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2305 000065C4 FF7F94111705        <1> 	db	-1,127,148,17,23,5 ; 13/06/2022
  2306 000065CA 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2307 000065D0 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2308 000065D6 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2309 000065DC 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2310 000065E2 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2311 000065E8 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2312 000065EE 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2313                              <1> 	;				;----- FUNCTIONS ------		
  2314 000065F2 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2315 000065F8 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2316 000065FE 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2317 00006604 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2318 0000660A 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2319                              <1> 
  2320                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2321 00006610 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2321 00006619 39302D3D0809        <1>
  2322 0000661F 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2322 00006628 705B5D0DFF61736466- <1>
  2322 00006631 67686A6B6C3B27      <1>
  2323 00006638 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2323 00006641 6D2C2E2FFF2AFF20FF  <1>
  2324                              <1> ;-----	LC TABLE SCAN
  2325 0000664A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2326 0000664F 4041424344          <1> 	db	64,65,66,67,68
  2327 00006654 FFFF                <1> 	db	-1,-1			; NL, SL
  2328                              <1> 
  2329                              <1> ;-----	KEYPAD TABLE
  2330 00006656 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2331 0000665C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2332 00006663 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2333                              <1> 
  2334                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2335 00006668 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2335 00006671 28295F2B0800        <1>
  2336 00006677 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2336 00006680 507B7D0DFF41534446- <1>
  2336 00006689 47484A4B4C3A22      <1>
  2337 00006690 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2337 00006699 4D3C3E3FFF2AFF20FF  <1>
  2338                              <1> ;-----	UC TABLE SCAN
  2339 000066A2 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2340 000066A7 595A5B5C5D          <1> 	db	89,90,91,92,93
  2341 000066AC FFFF                <1> 	db	-1,-1			; NL, SL
  2342                              <1> 
  2343                              <1> ;-----	NUM STATE TABLE
  2344 000066AE 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2344 000066B7 3233302E            <1>
  2345                              <1> 	;
  2346 000066BB FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2347                              <1> 
  2348                              <1> Align	4
  2349                              <1> ;----------------------------------------
  2350                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2351                              <1> ;----------------------------------------
  2352 000066C0 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2353 000066C1 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2354                              <1> 				; (29h default setting for video mode 3)
  2355                              <1> 				; Mode Select register Bits
  2356                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2357                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2358                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2359                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2360                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2361                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2362                              <1> 				;   BIT 6, 7 - Not Used
  2363                              <1> 
  2364                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2365                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2366                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2367                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2368                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2369                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2370                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2371                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2372                              <1> ; Mode & 37h = Video signal OFF
  2373                              <1> 			
  2374                              <1> 
  2375                              <1> ; 26/08/2014
  2376                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2377                              <1> ; Derived from IBM "pc-at" 
  2378                              <1> ; rombios source code (06/10/1985)
  2379                              <1> ; 'dseg.inc'
  2380                              <1> 
  2381                              <1> ;---------------------------------------;
  2382                              <1> ;	SYSTEM DATA AREA		;
  2383                              <1> ;----------------------------------------
  2384 000066C2 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2385                              <1> 
  2386                              <1> ;----------------------------------------
  2387                              <1> ;	KEYBOARD DATA AREAS		;
  2388                              <1> ;----------------------------------------
  2389                              <1> 
  2390 000066C3 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2391 000066C4 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2392 000066C5 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2393 000066C6 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2394 000066C7 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2395 000066C8 [D8660000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2396 000066CC [F8660000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2397 000066D0 [D8660000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2398 000066D4 [D8660000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2399                              <1> ; ------  HEAD = TAIL INDICATES THAT THE BUFFER IS EMPTY
  2400 000066D8 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2401                              <1> 
  2402                              <1> ; /// End Of KEYBOARD DATA ///
  2263                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2264                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2265                              <1> ; Last Modification: 11/03/2015
  2266                              <1> ;		    (Data section for 'VIDEO.INC')	
  2267                              <1> ;
  2268                              <1> ; ///////// VIDEO DATA ///////////////
  2269                              <1> 
  2270                              <1> video_params:
  2271                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2272                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2273                              <1> 	; VIDEO MODE 3
  2274 000066F8 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2275 000066FF 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2276 00006704 00000000            <1> 	db	0,0,0,0
  2277                              <1> 
  2278                              <1> ; /// End Of VIDEO DATA ///
  2264                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2265                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2266                              <1> ; Last Modification: 11/03/2015
  2267                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2268                              <1> ;
  2269                              <1> ; *****************************************************************************
  2270                              <1> 
  2271                              <1> ;----------------------------------------
  2272                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2273                              <1> ;	REFERENCED BY POST & BIOS	:
  2274                              <1> ;----------------------------------------
  2275                              <1> 
  2276 00006708 [6B670000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2277                              <1> 
  2278                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2279                              <1> ;----------------------------------------------------------------
  2280                              <1> ; DISK_BASE							:
  2281                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2282                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2283                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2284                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2285                              <1> ;----------------------------------------------------------------
  2286                              <1> 
  2287                              <1> ;DISK_BASE:	
  2288                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2289                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2290                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2291                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2292                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2293                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2294                              <1> ;	DB	01BH		; GAP LENGTH
  2295                              <1> ;	DB	0FFH		; DTL
  2296                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2297                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2298                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2299                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2300                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2301                              <1> 
  2302                              <1> ;----------------------------------------
  2303                              <1> ;	ROM BIOS DATA AREAS		:
  2304                              <1> ;----------------------------------------
  2305                              <1> 
  2306                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2307                              <1> 
  2308                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2309                              <1> 
  2310                              <1> ;----------------------------------------
  2311                              <1> ;	DISKETTE DATA AREAS		:
  2312                              <1> ;----------------------------------------
  2313                              <1> 
  2314                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2315                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2316                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2317                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2318                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2319                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2320                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2321                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2322                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2323                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2324                              <1> 
  2325                              <1> ;----------------------------------------
  2326                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2327                              <1> ;----------------------------------------
  2328                              <1> 
  2329                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2330                              <1> 
  2331                              <1> ;----------------------------------------
  2332                              <1> ;	TIMER DATA AREA 		:
  2333                              <1> ;----------------------------------------
  2334                              <1> 
  2335                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2336                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2337                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2338                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2339                              <1> 
  2340                              <1> ;----------------------------------------
  2341                              <1> ;	ADDITIONAL MEDIA DATA		:
  2342                              <1> ;----------------------------------------
  2343                              <1> 
  2344                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2345                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2346                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2347                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2348                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2349                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2350                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2351                              <1> 
  2352                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2353                              <1> 
  2354                              <1> ;--------------------------------------------------------
  2355                              <1> ;	DRIVE TYPE TABLE				:
  2356                              <1> ;--------------------------------------------------------
  2357                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2358                              <1> DR_TYPE:
  2359 0000670C 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2360                              <1>                 ;DW      MD_TBL1
  2361 0000670D [2A670000]          <1> 		dd	MD_TBL1
  2362 00006711 82                  <1> 		DB	02+BIT7ON
  2363                              <1> 		;DW      MD_TBL2
  2364 00006712 [37670000]          <1>                 dd      MD_TBL2
  2365 00006716 02                  <1> DR_DEFAULT:	DB	02
  2366                              <1>                 ;DW      MD_TBL3
  2367 00006717 [44670000]          <1> 		dd      MD_TBL3
  2368 0000671B 03                  <1> 		DB	03
  2369                              <1>                 ;DW      MD_TBL4
  2370 0000671C [51670000]          <1> 		dd      MD_TBL4
  2371 00006720 84                  <1> 		DB	04+BIT7ON
  2372                              <1>                 ;DW      MD_TBL5
  2373 00006721 [5E670000]          <1> 		dd      MD_TBL5
  2374 00006725 04                  <1> 		DB	04
  2375                              <1>                 ;DW      MD_TBL6
  2376 00006726 [6B670000]          <1> 		dd      MD_TBL6
  2377                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2378                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2379                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2380                              <1> ;--------------------------------------------------------
  2381                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2382                              <1> ;--------------------------------------------------------
  2383                              <1> ;--------------------------------------------------------
  2384                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2385                              <1> ;--------------------------------------------------------
  2386                              <1> MD_TBL1:        
  2387 0000672A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2388 0000672B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2389 0000672C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2390 0000672D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2391 0000672E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2392 0000672F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2393 00006730 FF                  <1> 	DB	0FFH		; DTL
  2394 00006731 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2395 00006732 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2396 00006733 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2397 00006734 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2398 00006735 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2399 00006736 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2400                              <1> ;--------------------------------------------------------
  2401                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2402                              <1> ;--------------------------------------------------------
  2403                              <1> MD_TBL2:        
  2404 00006737 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2405 00006738 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2406 00006739 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2407 0000673A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2408 0000673B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2409 0000673C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2410 0000673D FF                  <1> 	DB	0FFH		; DTL
  2411 0000673E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2412 0000673F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2413 00006740 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2414 00006741 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2415 00006742 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2416 00006743 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2417                              <1> ;--------------------------------------------------------
  2418                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2419                              <1> ;--------------------------------------------------------
  2420                              <1> MD_TBL3:
  2421 00006744 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2422 00006745 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2423 00006746 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2424 00006747 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2425 00006748 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2426 00006749 1B                  <1> 	DB	01BH		; GAP LENGTH
  2427 0000674A FF                  <1> 	DB	0FFH		; DTL
  2428 0000674B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2429 0000674C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2430 0000674D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2431 0000674E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2432 0000674F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2433 00006750 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2434                              <1> ;--------------------------------------------------------
  2435                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2436                              <1> ;--------------------------------------------------------
  2437                              <1> MD_TBL4:
  2438 00006751 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2439 00006752 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2440 00006753 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2441 00006754 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2442 00006755 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2443 00006756 2A                  <1> 	DB	02AH		; GAP LENGTH
  2444 00006757 FF                  <1> 	DB	0FFH		; DTL
  2445 00006758 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2446 00006759 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2447 0000675A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2448 0000675B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2449 0000675C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2450 0000675D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2451                              <1> ;--------------------------------------------------------
  2452                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2453                              <1> ;--------------------------------------------------------
  2454                              <1> MD_TBL5:
  2455 0000675E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2456 0000675F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2457 00006760 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2458 00006761 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2459 00006762 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2460 00006763 2A                  <1> 	DB	02AH		; GAP LENGTH
  2461 00006764 FF                  <1> 	DB	0FFH		; DTL
  2462 00006765 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2463 00006766 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2464 00006767 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2465 00006768 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2466 00006769 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2467 0000676A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2468                              <1> ;--------------------------------------------------------
  2469                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2470                              <1> ;--------------------------------------------------------
  2471                              <1> MD_TBL6:
  2472 0000676B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2473 0000676C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2474 0000676D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2475 0000676E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2476 0000676F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2477 00006770 1B                  <1> 	DB	01BH		; GAP LENGTH
  2478 00006771 FF                  <1> 	DB	0FFH		; DTL
  2479 00006772 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2480 00006773 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2481 00006774 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2482 00006775 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2483 00006776 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2484 00006777 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2485                              <1> 
  2486                              <1> 
  2487                              <1> ; << diskette.inc >>
  2488                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2489                              <1> ;
  2490                              <1> ;----------------------------------------
  2491                              <1> ;	ROM BIOS DATA AREAS		:
  2492                              <1> ;----------------------------------------
  2493                              <1> 
  2494                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2495                              <1> 
  2496                              <1> ;----------------------------------------
  2497                              <1> ;	FIXED DISK DATA AREAS		:
  2498                              <1> ;----------------------------------------
  2499                              <1> 
  2500                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2501                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2502                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2503                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2504                              <1> 
  2505                              <1> ;----------------------------------------
  2506                              <1> ;	ADDITIONAL MEDIA DATA		:
  2507                              <1> ;----------------------------------------
  2508                              <1> 
  2509                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2510                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2511                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2512                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2513                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2514                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2515                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2516                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2517                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2518                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2519                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2520                              <1> 
  2521                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2522                              <1> ;
  2523                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2524                              <1> 
  2525                              <1> ERR_TBL:
  2526 00006778 E0                  <1> 	db	NO_ERR
  2527 00006779 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2528 0000677D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2529                              <1> 
  2530                              <1> ; 17/12/2014 (mov ax, [cfd])
  2531                              <1> ; 11/12/2014
  2532 00006781 00                  <1> cfd:		db 0			; current floppy drive (for GET_PARM)
  2533                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2534 00006782 01                  <1> pfd:		db 1			; previous floppy drive (for GET_PARM)
  2535                              <1> 					; (initial value of 'pfd 
  2536                              <1> 					; must be different then 'cfd' value
  2537                              <1> 					; to force updating/initializing
  2538                              <1> 					; current drive parameters) 
  2539 00006783 90                  <1> align 2
  2540                              <1> 
  2541 00006784 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2542                              <1> 			      ; (170h)
  2543 00006786 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2544                              <1> 
  2545                              <1> ; 05/01/2015 
  2546 00006788 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2547                              <1> 
  2548                              <1> ; *****************************************************************************
  2265                                  ;;;
  2266                                  
  2267 00006789 90                      Align 2
  2268                                  
  2269                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2270 0000678A 00                      boot_drv:    db 0 ; boot drive number (physical)
  2271                                  ; 24/11/2014
  2272 0000678B 00                      drv:	     db 0 
  2273 0000678C 00                      last_drv:    db 0 ; last hdd
  2274 0000678D 00                      hdc:         db 0  ; number of hard disk drives
  2275                                  		     ; (present/detected)
  2276                                  ;
  2277                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2278                                  ; Physical drive type & flags
  2279 0000678E 00                      fd0_type:    db 0  ; floppy drive type
  2280 0000678F 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2281                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2282                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2283                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2284                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2285 00006790 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2286 00006791 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2287 00006792 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2288 00006793 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2289                                  		     ; bit 0 - Fixed disk access subset supported
  2290                                  		     ; bit 1 - Drive locking and ejecting
  2291                                  		     ; bit 2 - Enhanced disk drive support
  2292                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2293                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2294                                  		     ; will interpret it as 'LBA ready'!)		
  2295                                  
  2296                                  ; 11/03/2015 - 10/07/2015
  2297 00006794 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2297 0000679D 0000000000         
  2298 000067A2 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2298 000067AB 0000000000         
  2299 000067B0 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2299 000067B9 0000000000         
  2300 000067BE 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2300 000067C7 000000000000000000-
  2300 000067D0 000000000000000000-
  2300 000067D9 00                 
  2301 000067DA 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2302 000067E1 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2303                                  ;
  2304                                  
  2305                                  ; 27/08/2014
  2306                                  scr_row:
  2307 000067E8 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2308                                  scr_col:
  2309 000067EC 00000000                	dd 0
  2310                                  
  2311                                  ;; 14/08/2015
  2312                                  ;;msgPM:
  2313                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2314                                  msgKVER:
  2315                                  	;;;db "Retro UNIX 386 v1 - Kernel v0.2.0.17 [04/02/2016]", 0
  2316                                  	;;db "Retro UNIX 386 v1 - Kernel v0.2.0.18 [29/04/2022]", 0	
  2317                                  	;db "Retro UNIX 386 v1 - Kernel v0.2.0.19 [02/06/2022]", 0
  2318 000067F0 526574726F20554E49-     	db "Retro UNIX 386 v1 - Kernel v0.2.0.20 [14/06/2022]", 0
  2318 000067F9 582033383620763120-
  2318 00006802 2D204B65726E656C20-
  2318 0000680B 76302E322E302E3230-
  2318 00006814 205B31342F30362F32-
  2318 0000681D 3032325D00         
  2319                                  
  2320                                  Align 2
  2321                                  
  2322                                  ; 20/08/2014
  2323                                    ; /* This is the default interrupt "handler" :-) */ 
  2324                                    ; Linux v0.12 (head.s)
  2325                                  int_msg:
  2326 00006822 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2326 0000682B 6E7465727275707420-
  2326 00006834 212000             
  2327                                  
  2328 00006837 90                      Align 2  
  2329                                  
  2330                                  ; 21/08/2014
  2331                                  timer_msg:
  2332 00006838 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2332 00006841 542032306829202120-
  2332 0000684A 54696D657220496E74-
  2332 00006853 657272757074203A20 
  2333                                  tcountstr:
  2334 0000685C 303030303020            	db "00000 "
  2335 00006862 00                      	db 0
  2336                                  
  2337 00006863 90                      Align 2
  2338                                  	; 21/08/2014
  2339                                  exc_msg:
  2340 00006864 435055206578636570-     	db "CPU exception ! "
  2340 0000686D 74696F6E202120     
  2341                                  excnstr: 		; 25/08/2014
  2342 00006874 3F3F68202045495020-     	db "??h", "  EIP : "
  2342 0000687D 3A20               
  2343                                  EIPstr: ; 29/08/2014
  2344 0000687F 00<rep Ch>              	times 12 db 0
  2345                                  rtc_msg:
  2346 0000688B 5265616C2054696D65-     	db "Real Time Clock - "
  2346 00006894 20436C6F636B202D20 
  2347                                  datestr:
  2348 0000689D 30302F30302F303030-     	db "00/00/0000"
  2348 000068A6 30                 
  2349 000068A7 20                      	db " "
  2350                                  daystr:
  2351 000068A8 44415920                	db "DAY "
  2352                                  timestr:	
  2353 000068AC 30303A30303A3030                db "00:00:00"
  2354 000068B4 20                      	db " "
  2355 000068B5 00                      	db 0 
  2356                                  
  2357                                  daytmp:
  2358                                  	; 28/02/2015
  2359 000068B6 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2359 000068BF 4F4E20545545205745-
  2359 000068C8 442054485520465249-
  2359 000068D1 2053415420         
  2360                                  
  2361 000068D6 FF                      ptime_seconds: db 0FFh
  2362                                  
  2363                                  	; 23/02/2015
  2364                                  	; 25/08/2014
  2365                                  ;scounter:
  2366                                  ;	db 5
  2367                                  ;	db 19
  2368                                  
  2369                                  ;; 05/11/2014
  2370                                  ;msg_out_of_memory:
  2371                                  ;	db 	07h, 0Dh, 0Ah
  2372                                  ;	db      'Insufficient memory ! '
  2373                                  ;	db	'(Minimum 2 MB memory is needed.)'
  2374                                  ; 	db	0Dh, 0Ah, 0
  2375                                  	;
  2376                                  setup_error_msg:
  2377 000068D7 0D0A                    	db 0Dh, 0Ah
  2378 000068D9 4469736B2053657475-     	db 'Disk Setup Error!' 
  2378 000068E2 70204572726F7221   
  2379 000068EA 0D0A00                  	db 0Dh, 0Ah,0
  2380                                  
  2381                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2382                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2383                                  ;	  db 0 ; upper left row (for scroll)	
  2384                                  
  2385                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2386                                  ;	  db 24 ; lower right row (for scroll)
  2387                                  
  2388                                  
  2389                                  ; 06/11/2014 (Temporary Data)
  2390                                  ; Memory Information message
  2391                                  ; 14/08/2015
  2392                                  msg_memory_info:
  2393 000068ED 07                      	db	07h
  2394 000068EE 0D0A                    	db	0Dh, 0Ah
  2395                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2396 000068F0 546F74616C206D656D-     	db	"Total memory : "
  2396 000068F9 6F7279203A20       
  2397                                  mem_total_b_str: ; 10 digits
  2398 000068FF 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2398 00006908 302062797465730D0A 
  2399 00006911 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2399 0000691A 202020202020202020 
  2400                                  mem_total_p_str: ; 7 digits
  2401 00006923 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2401 0000692C 616765730D0A       
  2402 00006932 0D0A                    	db 	0Dh, 0Ah
  2403 00006934 46726565206D656D6F-     	db	"Free memory  : "
  2403 0000693D 727920203A20       
  2404                                  free_mem_b_str:  ; 10 digits
  2405 00006943 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2405 0000694C 3F2062797465730D0A 
  2406 00006955 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2406 0000695E 202020202020202020 
  2407                                  free_mem_p_str:  ; 7 digits
  2408 00006967 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2408 00006970 616765730D0A       
  2409 00006976 0D0A00                  	db	0Dh, 0Ah, 0
  2410                                  
  2411                                  dsk_ready_msg:
  2412 00006979 0D0A                    	db 	0Dh, 0Ah
  2413                                  dsktype:
  2414 0000697B 6664                    	db	'fd'
  2415                                  dskx:
  2416 0000697D 30                      	db	'0'
  2417 0000697E 20                      	db	20h
  2418 0000697F 697320524541445920-     	db 	'is READY ...'
  2418 00006988 2E2E2E             
  2419 0000698B 00                      	db 	0
  2420                                  nextline:
  2421 0000698C 0D0A00                  	db 	0Dh, 0Ah, 0
  2422                                  
  2423                                  ; KERNEL - SYSINIT Messages
  2424                                  ; 24/08/2015
  2425                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2426                                  ; 14/07/2013
  2427                                  ;kernel_init_err_msg:
  2428                                  ;	db 0Dh, 0Ah
  2429                                  ;	db 07h
  2430                                  ;	db 'Kernel initialization ERROR !'
  2431                                  ;	db 0Dh, 0Ah, 0 
  2432                                  ; 24/08/2015
  2433                                  ;;; (temporary kernel init message has been removed
  2434                                  ;;;  from 'sys_init' code)
  2435                                  ;kernel_init_ok_msg: 
  2436                                  ;	db 0Dh, 0Ah
  2437                                  ;	db 07h
  2438                                  ;	db 'Welcome to Retro UNIX 386 v1 Operating System !'
  2439                                  ;	db 0Dh, 0Ah
  2440                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.0.17)'
  2441                                  ;	db 0Dh, 0Ah, 0
  2442                                  panic_msg:
  2443 0000698F 0D0A07                  	db 0Dh, 0Ah, 07h
  2444 00006992 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2444 0000699B 726E656C2050616E69-
  2444 000069A4 632021             
  2445 000069A7 0D0A00                  	db 0Dh, 0Ah, 0
  2446                                  etc_init_err_msg:
  2447 000069AA 0D0A                    	db 0Dh, 0Ah
  2448 000069AC 07                      	db 07h
  2449 000069AD 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2449 000069B6 74632F696E69742021-
  2449 000069BF 3F                 
  2450 000069C0 0D0A00                  	db 0Dh, 0Ah, 0
  2451                                  
  2452                                  ; 10/05/2015
  2453                                  badsys_msg:
  2454 000069C3 0D0A                    	db 0Dh, 0Ah
  2455 000069C5 07                      	db 07h
  2456 000069C6 496E76616C69642053-     	db 'Invalid System Call !'
  2456 000069CF 797374656D2043616C-
  2456 000069D8 6C2021             
  2457 000069DB 0D0A                    	db 0Dh, 0Ah
  2458 000069DD 4541583A20              	db 'EAX: '
  2459                                  bsys_msg_eax:
  2460 000069E2 303030303030303068      	db '00000000h'
  2461 000069EB 0D0A                    	db 0Dh, 0Ah
  2462 000069ED 4549503A20              	db 'EIP: '
  2463                                  bsys_msg_eip:
  2464 000069F2 303030303030303068      	db '00000000h' 
  2465 000069FB 0D0A00                  	db 0Dh, 0Ah, 0
  2466                                  
  2467                                  BSYS_M_SIZE equ $ - badsys_msg
  2468                                  
  2469                                  
  2470                                  align 2
  2471                                  
  2472                                  ; EPOCH Variables
  2473                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2474                                  ; 09/04/2013 epoch variables
  2475                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2476                                  ;
  2477 000069FE B207                    year: 	dw 1970
  2478                                  ;month: dw 1
  2479                                  ;day: 	dw 1
  2480                                  ;hour: 	dw 0
  2481                                  ;minute: dw 0
  2482                                  ;second: dw 0
  2483                                  ; 02/06/2022
  2484 00006A00 01                      month:	db 1
  2485 00006A01 01                      day:	db 1
  2486 00006A02 01                      hour:	db 1
  2487 00006A03 01                      minute: db 1
  2488 00006A04 01                      second:	db 1
  2489 00006A05 01                      	db 1
  2490                                  
  2491                                  DMonth:
  2492 00006A06 0000                    	dw 0
  2493 00006A08 1F00                    	dw 31
  2494 00006A0A 3B00                    	dw 59
  2495 00006A0C 5A00                    	dw 90
  2496 00006A0E 7800                    	dw 120
  2497 00006A10 9700                    	dw 151
  2498 00006A12 B500                    	dw 181
  2499 00006A14 D400                    	dw 212
  2500 00006A16 F300                    	dw 243
  2501 00006A18 1101                    	dw 273
  2502 00006A1A 3001                    	dw 304
  2503 00006A1C 4E01                    	dw 334
  2504                                  
  2505                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2506 00006A1E 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2507                                                       ; 1 and 16 MB, max. 3C00h = 15 MB.
  2508 00006A20 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2509                                  		   ;   between 16 MB and 4 GB.
  2510                                  
  2511 00006A22 90<rep Eh>              align 16
  2512                                  
  2513                                  bss_start:
  2514                                  
  2515                                  ABSOLUTE bss_start
  2516                                  
  2517                                  	; 11/03/2015
  2518                                  	; Interrupt Descriptor Table (20/08/2014)
  2519                                  idt:
  2520 00006A30 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2521                                  idt_end:
  2522                                  
  2523                                  ;alignb 4
  2524                                  
  2525                                  task_state_segment:
  2526                                  	; 24/03/2015
  2527 00006C30 ????                    tss.link:   resw 1
  2528 00006C32 ????                    	    resw 1
  2529                                  ; tss offset 4	
  2530 00006C34 ????????                tss.esp0:   resd 1
  2531 00006C38 ????                    tss.ss0:    resw 1
  2532 00006C3A ????                    	    resw 1	
  2533 00006C3C ????????                tss.esp1:   resd 1
  2534 00006C40 ????                    tss.ss1:    resw 1
  2535 00006C42 ????                    	    resw 1 	
  2536 00006C44 ????????                tss.esp2:   resd 1
  2537 00006C48 ????                    tss.ss2:    resw 1
  2538 00006C4A ????                    	    resw 1
  2539                                  ; tss offset 28
  2540 00006C4C ????????                tss.CR3:    resd 1
  2541 00006C50 ????????                tss.eip:    resd 1
  2542 00006C54 ????????                tss.eflags: resd 1
  2543                                  ; tss offset 40
  2544 00006C58 ????????                tss.eax:    resd 1		 		
  2545 00006C5C ????????                tss.ecx:    resd 1
  2546 00006C60 ????????                tss.edx:    resd 1
  2547 00006C64 ????????                tss.ebx:    resd 1
  2548 00006C68 ????????                tss.esp:    resd 1
  2549 00006C6C ????????                tss.ebp:    resd 1
  2550 00006C70 ????????                tss.esi:    resd 1
  2551 00006C74 ????????                tss.edi:    resd 1
  2552                                  ; tss offset 72
  2553 00006C78 ????                    tss.ES:     resw 1
  2554 00006C7A ????                    	    resw 1	
  2555 00006C7C ????                    tss.CS:	    resw 1
  2556 00006C7E ????                    	    resw 1
  2557 00006C80 ????                    tss.SS:	    resw 1
  2558 00006C82 ????                    	    resw 1
  2559 00006C84 ????                    tss.DS:	    resw 1
  2560 00006C86 ????                    	    resw 1
  2561 00006C88 ????                    tss.FS:	    resw 1
  2562 00006C8A ????                    	    resw 1
  2563 00006C8C ????                    tss.GS:	    resw 1
  2564 00006C8E ????                    	    resw 1		
  2565 00006C90 ????                    tss.LDTR:   resw 1
  2566 00006C92 ????                    	    resw 1
  2567                                  ; tss offset 100		
  2568 00006C94 ????                    	    resw 1		
  2569 00006C96 ????                    tss.IOPB:   resw 1
  2570                                  ; tss offset 104 
  2571                                  tss_end:
  2572                                  
  2573 00006C98 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2574                                  		    ; (Physical address = Virtual address)	 	
  2575 00006C9C ????????                memory_size: resd 1 ; memory size in pages
  2576 00006CA0 ????????                free_pages:  resd 1 ; number of free pages		
  2577 00006CA4 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2578                                  		    ; first free page search
  2579 00006CA8 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2580                                  		    ; next free page search will be
  2581                                  		    ; stopped after it. (end of M.A.T.)
  2582 00006CAC ????????                first_page:  resd 1 ; offset value in M.A.T. which
  2583                                  		    ; first free page search
  2584                                  		    ; will be started on it. (for user)
  2585 00006CB0 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2586                                  
  2587                                  ;;;
  2588                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2589                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2590 00006CB4 ????                    CRT_START:   resw 1 ; starting address in regen buffer
  2591                                  		    ; NOTE: active page only
  2592 00006CB6 <res 10h>               cursor_posn: resw 8 ; cursor positions for video pages
  2593                                  active_page: 
  2594 00006CC6 ??                      ptty: 	     resb 1 ; current tty
  2595                                  ; 01/07/2015
  2596 00006CC7 ??                      ccolor:	     resb 1 ; current color attributes ('sysmsg')	
  2597                                  ; 26/10/2015
  2598                                  ; 07/09/2014
  2599 00006CC8 <res 14h>               ttychr:      resw ntty+2 ; Character buffer (multiscreen)
  2600                                  
  2601                                  ; 21/08/2014
  2602 00006CDC ????????                tcount:	     resd 1
  2603                                  
  2604                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2605 00006CE0 ????????                p_time:      resd 1 ; present time (for systime & sysmdate)
  2606                                  
  2607                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2608                                  ; (open mode locks for pseudo TTYs)
  2609                                  ; [ major tty locks (return error in any conflicts) ]
  2610 00006CE4 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2611                                  
  2612                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2613                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2614 00006CF8 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2615                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2616                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2617                                  ;; 0 means serial port is not available 
  2618                                  ;;comprm: ; 25/06/2014
  2619 00006D02 ??                      com1p:       resb 1 ;;0E3h
  2620 00006D03 ??                      com2p:       resb 1 ;;0E3h
  2621                                  
  2622                                  ; 17/11/2015
  2623                                  ; request for response (from the terminal)	
  2624 00006D04 ????                    req_resp:     resw 1 			
  2625                                  ; 07/11/2015
  2626 00006D06 ??                      ccomport:    resb 1 ; current COM (serial) port
  2627                                  		    ; (0= COM1, 1= COM2)
  2628                                  ; 09/11/2015
  2629 00006D07 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2630                                  ; 07/11/2015
  2631 00006D08 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2632 00006D0A ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2633                                  
  2634                                  ; 23/10/2015
  2635                                  ; SERIAL PORTS - COMMUNICATION MODES
  2636                                  ; (Retro UNIX 386 v1 feature only!)
  2637                                  ; 0 - command mode (default/initial mode)
  2638                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2639                                  ;;; communication modes for future versions:  
  2640                                  ; // 2 - keyboard mode (ascii+scancode input)
  2641                                  ; // 3 - mouse mode
  2642                                  ; // 4 - device control (output) mode
  2643                                  ; VALID COMMANDS for current version:
  2644                                  ; 	'LOGIN'
  2645                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2646                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2647                                  ;  Login response: db 0FFh, 'login', 0
  2648                                  ;	 ("login request accepted, wait for login prompt") 
  2649                                  ; When a login requests is received and acknowledged (by
  2650                                  ; serial port interrupt handler (communication procedure),
  2651                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2652                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2653                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2654                                  ; 
  2655                                  ; 'sys connect' system call is used to change communication mode
  2656                                  ; except 'LOGIN' command which is used to start terminal mode
  2657                                  ; by using (COM port) terminal.
  2658                                  
  2659                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2660                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2661                                  ;com1mode:    resb 1 ; communication mode for COM1
  2662                                  ;com1com:     resb 1 ; communication command for COM1
  2663                                  ;com2mode:    resb 1 ; communication mode for COM1
  2664                                  ;com2com      resb 1 ; communication command for COM1
  2665                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2666                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2667                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2668                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2669                                  
  2670                                  ; 22/08/2014 (RTC)
  2671                                  ; (Packed BCD)
  2672 00006D0C ??                      time_seconds: resb 1
  2673 00006D0D ??                      time_minutes: resb 1
  2674 00006D0E ??                      time_hours:   resb 1
  2675 00006D0F ??                      date_wday:    resb 1
  2676 00006D10 ??                      date_day:     resb 1
  2677 00006D11 ??                      date_month:   resb 1			
  2678 00006D12 ??                      date_year:    resb 1
  2679 00006D13 ??                      date_century: resb 1
  2680                                  
  2681                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2682                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2683                              <1> ; Last Modification: 10/07/2015
  2684                              <1> ;	(Unnitialized Disk Parameters Data section for 'DISKIO.INC') 
  2685                              <1> ;
  2686                              <1> ; *****************************************************************************
  2687                              <1> 
  2688                              <1> alignb 2
  2689                              <1> 
  2690                              <1> ;----------------------------------------
  2691                              <1> ;	TIMER DATA AREA 		:
  2692                              <1> ;----------------------------------------
  2693                              <1> 
  2694                              <1> TIMER_LH:	; 16/02/205
  2695 00006D14 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2696 00006D16 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2697 00006D18 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2698                              <1> 
  2699                              <1> ;----------------------------------------
  2700                              <1> ;	DISKETTE DATA AREAS		:
  2701                              <1> ;----------------------------------------
  2702                              <1> 
  2703 00006D19 ??                  <1> SEEK_STATUS:	resb	1
  2704 00006D1A ??                  <1> MOTOR_STATUS:	resb	1
  2705 00006D1B ??                  <1> MOTOR_COUNT:	resb	1
  2706 00006D1C ??                  <1> DSKETTE_STATUS:	resb	1
  2707 00006D1D ??????????????      <1> NEC_STATUS:	resb	7
  2708                              <1> 
  2709                              <1> ;----------------------------------------
  2710                              <1> ;	ADDITIONAL MEDIA DATA		:
  2711                              <1> ;----------------------------------------
  2712                              <1> 
  2713 00006D24 ??                  <1> LASTRATE:	resb 	1
  2714 00006D25 ??                  <1> HF_STATUS:	resb 	1
  2715 00006D26 ??                  <1> HF_ERROR:	resb 	1
  2716 00006D27 ??                  <1> HF_INT_FLAG:	resb 	1
  2717 00006D28 ??                  <1> HF_CNTRL:	resb 	1
  2718 00006D29 ????????            <1> DSK_STATE:	resb 	4
  2719 00006D2D ????                <1> DSK_TRK:	resb 	2
  2720                              <1> 
  2721                              <1> ;----------------------------------------
  2722                              <1> ;	FIXED DISK DATA AREAS		:
  2723                              <1> ;----------------------------------------
  2724                              <1> 
  2725 00006D2F ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2726 00006D30 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2727 00006D31 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2728                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2729                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2730                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2731                              <1> 
  2732 00006D32 ????                <1> alignb 4
  2733                              <1> 
  2734                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2735                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2736                              <1> HF_TBL_VEC: ; 22/12/2014	
  2737 00006D34 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2738 00006D38 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2739 00006D3C ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2740 00006D40 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2741                              <1> 
  2742                              <1> ; 03/01/2015
  2743 00006D44 ??                  <1> LBAMode:     	resb	1
  2744                              <1> 
  2745                              <1> ; *****************************************************************************
  2682                                  
  2683                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2684                                  
  2685                                  ;alignb 2
  2686                                  
  2687                                  ; 27/02/2022
  2688                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2689                                  
  2690                                  ; 23/02/2022
  2691                                  ;; Memory (swap) Data (11/03/2015)
  2692                                  ; 09/03/2015
  2693                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2694                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2695                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes). 		  				
  2696                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2697                                  ;swpd_next:  resd 1 ; next free page block
  2698                                  ;swpd_last:  resd 1 ; last swap page block	
  2699                                  
  2700 00006D45 ??????                  alignb 4
  2701                                  
  2702                                  ; 10/07/2015
  2703                                  ; 28/08/2014
  2704 00006D48 ????????                error_code:	resd 1
  2705                                  ; 29/08/2014
  2706 00006D4C ????????                FaultOffset: 	resd 1
  2707                                  ; 21/09/2015
  2708 00006D50 ????????                PF_Count:	resd 1	; total page fault count
  2709                                  		       	; (for debugging - page fault analyze)
  2710                                  		 	; 'page _fault_handler' (memory.inc)
  2711                                  			; 'sysgeterr' (u9.s)
  2712                                  ; 23/02/2022
  2713 00006D54 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2714                                  			;  for a system call in next retro unix 386 version)
  2715                                  			; -2 ticks per second-
  2716                                  ;; 21/08/2015
  2717                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2718                                  
  2719                                  ; 27/02/2022
  2720                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2721                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYSX.INC (ux.s)
  2722                              <1> ; Last Modification: 14/05/2022
  2723                              <1> ;
  2724                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2725                              <1> ; (Modified from 
  2726                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2727                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2728                              <1> ; ----------------------------------------------------------------------------
  2729                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2730                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2731                              <1> ; <Bell Laboratories (17/3/1972)>
  2732                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2733                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2734                              <1> ; ****************************************************************************
  2735                              <1> ; 13/11/2015
  2736                              <1> 
  2737                              <1> alignb 2
  2738                              <1> 
  2739                              <1> inode:
  2740                              <1> 	; 11/03/2013. 
  2741                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2742                              <1> 	;i.
  2743                              <1> 
  2744 00006D58 ????                <1> 	i.flgs:	 resw 1
  2745 00006D5A ??                  <1> 	i.nlks:	 resb 1
  2746 00006D5B ??                  <1> 	i.uid:	 resb 1
  2747 00006D5C ????                <1>         i.size:  resw 1 ; size
  2748 00006D5E <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2749 00006D6E ????????            <1> 	i.ctim:	 resd 1
  2750 00006D72 ????????            <1> 	i.mtim:	 resd 1
  2751 00006D76 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2752                              <1> 
  2753                              <1> I_SIZE	equ $ - inode 
  2754                              <1> 
  2755                              <1> process:
  2756                              <1> 	; 26/02/2022
  2757                              <1> 	; 04/02/2022
  2758                              <1> 	; 06/05/2015
  2759                              <1> 	; 11/03/2013 - 05/02/2014
  2760                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2761                              <1> 	;p.
  2762                              <1> 	
  2763 00006D78 <res 20h>           <1>         p.pid:   resw nproc
  2764 00006D98 <res 20h>           <1>         p.ppid:  resw nproc
  2765                              <1>         ;p.break: resw nproc ; 04/02/2022 (p.break is not used)
  2766 00006DB8 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2767                              <1> 	; 26/02/2022 (p.waitc is not used)
  2768                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2769 00006DC8 <res 10h>           <1> 	p.link:	 resb nproc
  2770 00006DD8 <res 10h>           <1> 	p.stat:	 resb nproc
  2771                              <1> 
  2772                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2773 00006DE8 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2774                              <1> 			    ; 'user' structure	
  2775                              <1> 
  2776                              <1> 
  2777                              <1> P_SIZE	equ $ - process
  2778                              <1> 
  2779                              <1> 
  2780                              <1> ; fsp table (original UNIX v1)
  2781                              <1> ;
  2782                              <1> ;Entry
  2783                              <1> ;          15                                      0
  2784                              <1> ;  1     |---|---------------------------------------|
  2785                              <1> ;        |r/w|       i-number of open file           |
  2786                              <1> ;        |---|---------------------------------------| 
  2787                              <1> ;        |               device number               |
  2788                              <1> ;        |-------------------------------------------|
  2789                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2790                              <1> ;        |-------------------------------------------| 
  2791                              <1> ;        |  flag that says    | number of processes  |
  2792                              <1> ;        |   file deleted     | that have file open  |
  2793                              <1> ;        |-------------------------------------------| 
  2794                              <1> ;  2     |                                           |
  2795                              <1> ;        |-------------------------------------------| 
  2796                              <1> ;        |                                           |
  2797                              <1> ;        |-------------------------------------------|
  2798                              <1> ;        |                                           |
  2799                              <1> ;        |-------------------------------------------|
  2800                              <1> ;        |                                           |
  2801                              <1> ;        |-------------------------------------------| 
  2802                              <1> ;  3     |                                           | 
  2803                              <1> ;        |                                           |  
  2804                              <1> ;
  2805                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2806                              <1> 
  2807                              <1> 
  2808                              <1> ; 15/04/2015
  2809 00006E28 <res 1F4h>          <1> fsp:	 resb nfiles * 10 ; 11/05/2015 (8 -> 10)
  2810 0000701C <res 20h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2811 0000703C ????                <1> ii:	 resw 1
  2812 0000703E ????                <1> idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2813 00007040 ????                <1> cdev:    resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2814                              <1> ; 18/05/2015
  2815                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2816                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2817                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2818                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2819                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2820                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2821                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2822                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2823                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2824                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2825                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2826 00007042 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2827                              <1> 	        ; as above, for physical drives numbers in following table
  2828 00007043 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2829                              <1> ; 15/04/2015
  2830 00007044 ??                  <1> active:	 resb 1 
  2831 00007045 ??                  <1> 	 resb 1 ; 09/06/2015
  2832 00007046 ????                <1> mnti:	 resw 1
  2833 00007048 ????                <1> mntp:	 resw 1 ; 14/05/2022 ; (parent dir inumber of [mnti])
  2834 0000704A ????                <1> mpid:	 resw 1
  2835 0000704C ????                <1> rootdir: resw 1
  2836                              <1> ; 14/02/2014
  2837                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2838                              <1> ;		      Single level run queue
  2839                              <1> ;		      (in order to solve sleep/wakeup lock)
  2840 0000704E ????                <1> runq:	 resw 1
  2841 00007050 ??                  <1> imod:	 resb 1
  2842 00007051 ??                  <1> smod:	 resb 1
  2843 00007052 ??                  <1> mmod:	 resb 1
  2844 00007053 ??                  <1> sysflg:	 resb 1
  2845                              <1> 
  2846                              <1> alignb 4
  2847                              <1> 
  2848                              <1> user:
  2849                              <1> 	; 18/10/2015
  2850                              <1> 	; 12/10/2015
  2851                              <1> 	; 21/09/2015
  2852                              <1> 	; 24/07/2015
  2853                              <1> 	; 16/06/2015
  2854                              <1> 	; 09/06/2015
  2855                              <1> 	; 11/05/2015
  2856                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2857                              <1> 	; 10/10/2013
  2858                              <1> 	; 11/03/2013. 
  2859                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2860                              <1> 	;u.
  2861                              <1> 
  2862 00007054 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2863 00007058 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2864 0000705C ????????            <1> 	u.r0:	  resd 1 ; eax
  2865 00007060 ????                <1> 	u.cdir:	  resw 1
  2866 00007062 <res Ah>            <1> 	u.fp:	  resb 10
  2867 0000706C ????????            <1> 	u.fofp:	  resd 1
  2868 00007070 ????????            <1> 	u.dirp:	  resd 1
  2869 00007074 ????????            <1> 	u.namep:  resd 1
  2870 00007078 ????????            <1> 	u.off:	  resd 1
  2871 0000707C ????????            <1> 	u.base:	  resd 1
  2872 00007080 ????????            <1> 	u.count:  resd 1
  2873 00007084 ????????            <1> 	u.nread:  resd 1
  2874 00007088 ????????            <1> 	u.break:  resd 1 ; break
  2875 0000708C ????                <1> 	u.ttyp:	  resw 1 
  2876 0000708E <res Ah>            <1> 	u.dirbuf: resb 10
  2877                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2878 00007098 ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2879 00007099 ??                  <1> 	u.pri:	  resb 1 ; 
  2880 0000709A ????                <1> 	u.intr:	  resw 1
  2881 0000709C ????                <1> 	u.quit:	  resw 1
  2882                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2883 0000709E ????                <1> 	u.ilgins: resw 1
  2884 000070A0 ????                <1> 	u.cdrv:	  resw 1 ; cdev
  2885 000070A2 ??                  <1> 	u.uid:	  resb 1 ; uid
  2886 000070A3 ??                  <1> 	u.ruid:	  resb 1
  2887 000070A4 ??                  <1> 	u.bsys:	  resb 1
  2888 000070A5 ??                  <1> 	u.uno:	  resb 1
  2889 000070A6 ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2890                              <1> 	; tty number (rtty, rcvt, wtty)
  2891 000070AA ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2892                              <1> 	; last error number
  2893 000070AB ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2894                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2895 000070AF ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2896 000070B3 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2897 000070B7 ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2898 000070BB ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2899                              <1> 	;u.pncount: resw 1 
  2900                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2901                              <1> 	;u.pnbase:  resd 1 
  2902                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2903                              <1> 			 ; 09/06/2015
  2904 000070BD ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2905 000070BE ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2906                              <1> 			 ; 24/07/2015 - 24/06/2015
  2907                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2908                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2909                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2910                              <1>  			 ; 24/06/2015	  	
  2911                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2912                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2913                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2914 000070BF ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2915                              <1> 
  2916 000070C3 ??                  <1> alignb 4
  2917                              <1> 
  2918                              <1> U_SIZE	equ $ - user
  2919                              <1> 
  2920                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2921 000070C4 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2922 000070C8 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2923 000070CC ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2924 000070D0 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2925 000070D2 ????                <1> argc:	resw 1	; argument count for 'sysexec'
  2926 000070D4 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  2927                              <1> 
  2928                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  2929                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  2930 000070D8 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  2931 000070D9 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  2932 000070DA ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  2933 000070DB ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  2934                              <1> 
  2935                              <1> ;alignb 4
  2936                              <1> 
  2937                              <1> ; 22/08/2015
  2938 000070DC <res C30h>          <1> buffer: resb nbuf * 520
  2939                              <1> 
  2940 00007D0C ????????????????    <1> sb0:	resd 2
  2941                              <1> ;s:
  2942                              <1> ; (root disk) super block buffer
  2943                              <1> systm:
  2944                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  2945                              <1> 	; 11/03/2013. 
  2946                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  2947                              <1> 	;s.
  2948                              <1> 
  2949 00007D14 ????                <1> 	resw 1
  2950 00007D16 <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  2951 00007E7E ????                <1> 	resw 1
  2952 00007E80 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  2953                              <1> eofitab equ $ - systm ; 12/02/2022 (end of inode table)
  2954 00007EA0 ????????            <1> 	s.time:	 resd 1
  2955 00007EA4 ????????            <1> 	s.syst:	 resd 1
  2956 00007EA8 ????????            <1>         s.wait_: resd 1 ; wait
  2957 00007EAC ????????            <1> 	s.idlet: resd 1
  2958 00007EB0 ????????            <1> 	s.chrgt: resd 1
  2959 00007EB4 ????                <1> 	s.drerr: resw 1
  2960                              <1> 
  2961                              <1> S_SIZE	equ $ - systm
  2962                              <1> 
  2963 00007EB6 <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  2964                              <1> 
  2965 00007F14 ????????????????    <1> sb1:	resd 2
  2966                              <1> ; (mounted disk) super block buffer
  2967                              <1> mount:	
  2968 00007F1C <res 200h>          <1> 	resb 512  ; 03/06/2015
  2969                              <1> 
  2970                              <1> ;/ ux -- unix
  2971                              <1> ;
  2972                              <1> ;systm:
  2973                              <1> ;
  2974                              <1> ;	.=.+2
  2975                              <1> ;	.=.+128.
  2976                              <1> ;	.=.+2
  2977                              <1> ;	.=.+64.
  2978                              <1> ;	s.time: .=.+4
  2979                              <1> ;	s.syst: .=.+4
  2980                              <1> ;	s.wait: .=.+4
  2981                              <1> ;	s.idlet:.=.+4
  2982                              <1> ;	s.chrgt:.=.+4
  2983                              <1> ;	s.drerr:.=.+2
  2984                              <1> ;inode:
  2985                              <1> ;	i.flgs: .=.+2
  2986                              <1> ;	i.nlks: .=.+1
  2987                              <1> ;	i.uid:  .=.+1
  2988                              <1> ;	i.size: .=.+2
  2989                              <1> ;	i.dskp: .=.+16.
  2990                              <1> ;	i.ctim: .=.+4
  2991                              <1> ;	i.mtim: .=.+4
  2992                              <1> ;	. = inode+32.
  2993                              <1> ;mount:	.=.+1024.
  2994                              <1> ;proc:
  2995                              <1> ;	p.pid:  .=.+[2*nproc]
  2996                              <1> ;	p.dska: .=.+[2*nproc]
  2997                              <1> ;	p.ppid: .=.+[2*nproc]
  2998                              <1> ;	p.break:.=.+[2*nproc]
  2999                              <1> ;	p.link: .=.+nproc
  3000                              <1> ;	p.stat: .=.+nproc
  3001                              <1> ;tty:
  3002                              <1> ;	. = .+[ntty*8.]
  3003                              <1> ;fsp:	.=.+[nfiles*8.]
  3004                              <1> ;bufp:	.=.+[nbuf*2]+6
  3005                              <1> ;sb0:	.=.+8
  3006                              <1> ;sb1:	.=.+8
  3007                              <1> ;swp:	.=.+8
  3008                              <1> ;ii:	.=.+2
  3009                              <1> ;idev:	.=.+2
  3010                              <1> ;cdev:	.=.+2
  3011                              <1> ;deverr: .=.+12.
  3012                              <1> ;active: .=.+2
  3013                              <1> ;rfap:	.=.+2
  3014                              <1> ;rkap:	.=.+2
  3015                              <1> ;tcap:	.=.+2
  3016                              <1> ;tcstate:.=.+2
  3017                              <1> ;tcerrc: .=.+2
  3018                              <1> ;mnti:	.=.+2
  3019                              <1> ;mntd:	.=.+2
  3020                              <1> ;mpid:	.=.+2
  3021                              <1> ;clockp: .=.+2
  3022                              <1> ;rootdir:.=.+2
  3023                              <1> ;toutt:	.=.+16.
  3024                              <1> ;touts: .=.+32.
  3025                              <1> ;runq:	.=.+6
  3026                              <1> ;
  3027                              <1> ;wlist:	.=.+40.
  3028                              <1> ;cc:	.=.+30.
  3029                              <1> ;cf:	.=.+31.
  3030                              <1> ;cl:	.=.+31.
  3031                              <1> ;clist:	.=.+510.
  3032                              <1> ;imod:	.=.+1
  3033                              <1> ;smod:	.=.+1
  3034                              <1> ;mmod:	.=.+1
  3035                              <1> ;uquant: .=.+1
  3036                              <1> ;sysflg: .=.+1
  3037                              <1> ;pptiflg:.=.+1
  3038                              <1> ;ttyoch: .=.+1
  3039                              <1> ; .even
  3040                              <1> ; .=.+100.; sstack:
  3041                              <1> ;buffer: .=.+[ntty*140.]
  3042                              <1> ;	.=.+[nbuf*520.]
  3043                              <1> ;
  3044                              <1> ; . = core-64.
  3045                              <1> ;user:
  3046                              <1> ;	u.sp:    .=.+2
  3047                              <1> ;	u.usp:   .=.+2
  3048                              <1> ;	u.r0:    .=.+2
  3049                              <1> ;	u.cdir:  .=.+2
  3050                              <1> ;	u.fp:    .=.+10.
  3051                              <1> ;	u.fofp:  .=.+2
  3052                              <1> ;	u.dirp:  .=.+2
  3053                              <1> ;	u.namep: .=.+2
  3054                              <1> ;	u.off:   .=.+2
  3055                              <1> ;	u.base:  .=.+2
  3056                              <1> ;	u.count: .=.+2
  3057                              <1> ;	u.nread: .=.+2
  3058                              <1> ;	u.break: .=.+2
  3059                              <1> ;	u.ttyp:  .=.+2
  3060                              <1> ;	u.dirbuf:.=.+10.
  3061                              <1> ;	u.pri:   .=.+2
  3062                              <1> ;	u.intr:  .=.+2
  3063                              <1> ;	u.quit:  .=.+2
  3064                              <1> ;	u.emt:   .=.+2
  3065                              <1> ;	u.ilgins:.=.+2
  3066                              <1> ;	u.cdev:  .=.+2
  3067                              <1> ;	u.uid:   .=.+1
  3068                              <1> ;	u.ruid:  .=.+1
  3069                              <1> ;	u.bsys:  .=.+1
  3070                              <1> ;	u.uno:   .=.+1
  3071                              <1> ;. = core
  2721                                  
  2722                                  bss_end:
  2723                                  
  2724                                  ; 27/02/2022
  2725                                  BSS_SIZE equ bss_end - bss_start
  2726                                  
  2727                                  ; 27/12/2013
  2728                                  _end:  ; end of kernel code (and read only data, just before bss)
